sing-box 配置无法启动怎么办:JSON 格式、字段迁移、DNS 规则与日志查看
sing-box 内核启动报错、GUI 客户端提示配置无效、或者启动后几秒退出。本文按报错类型整理:JSON 语法、字段在不同版本间的差异与迁移(geosite / geoip → rule_set、inbound 字段调整、legacy 选项移除)、DNS 规则常见错误、TUN 需要的权限,以及用 sing-box check 和日志精确定位问题。
先做一件事:sing-box check
不管用的是 GUI 客户端(GUI.for.SingBox、Hiddify、NekoBox、Karing、sing-box 官方 App)还是命令行,报错定位的第一步都是让内核自己检查配置:
sing-box check -c config.json
通过了什么都不输出;没通过会给出具体错误和位置。GUI 客户端内部也是调这个命令,只是提示有时被截断,自己在终端跑一次能看到完整信息。
配置格式化(修正缩进、排序字段)用 sing-box format -c config.json -w,它也会在格式化过程中暴露语法错误。
一、JSON 语法错误
报错样例
decode config: json: invalid character '}' looking for beginning of object key string
decode config: json: unexpected end of JSON input
invalid character '/' looking for beginning of value
常见原因
- 尾逗号:数组或对象最后一个元素后面多了逗号。这是从 YAML 或 JavaScript 转过来最常犯的错。
- 注释:标准 JSON 不允许
//或/* */注释。sing-box 1.9 以后对部分扫描场景容忍注释,但保险起见不要写。 - 引号:键名没加双引号、用了单引号、中文引号。
- 括号不配对:删节点或改规则时少删了一个
}。 - 编码:文件保存成了 UTF-8 with BOM 或 GBK,开头多出不可见字符。用编辑器另存为 UTF-8(无 BOM)。
处理:把报错里的字符位置或行号对到配置文件,或者整段复制到在线 JSON 校验器。用 VS Code 一类编辑器打开 .json 文件会自动标红语法错误。
二、字段版本差异与迁移
sing-box 的配置格式在 1.8、1.10、1.11、1.12 几个版本都有不兼容的调整。订阅转换工具、教程、GitHub 上的模板很多还是旧写法,拿到新内核上直接报错。
1.8:rule_set 替代 geosite / geoip
旧写法(1.7 及以前)
"route": {
"rules": [
{ "geosite": "cn", "geoip": "cn", "outbound": "direct" }
],
"geoip": { "download_url": "..." },
"geosite": { "download_url": "..." }
}
新写法(1.8+)
"route": {
"rules": [
{ "rule_set": ["geosite-cn", "geoip-cn"], "outbound": "direct" }
],
"rule_set": [
{ "tag": "geosite-cn", "type": "remote", "format": "binary",
"url": "https://.../geosite-cn.srs", "download_detour": "direct" },
{ "tag": "geoip-cn", "type": "remote", "format": "binary",
"url": "https://.../geoip-cn.srs", "download_detour": "direct" }
]
}
download_detour 要指向一个能访问到规则源的出站。规则源在 GitHub 上而当前又没有可用代理时,首次启动会卡在下载;用国内镜像源或先把 .srs 文件下到本地改成 "type": "local"。
1.10:inbound 的 sniff / domain_strategy 移到 route
旧配置在每个 inbound 里写 "sniff": true、"sniff_override_destination": true、"domain_strategy": "ipv4_only"。1.10 开始这些选项改为 route.rules 里的 action: "sniff" 和 action: "resolve",旧写法先是警告,1.11 后被移除。
1.11:block / dns 类型 outbound 移除
"type": "block" 和 "type": "dns" 的 outbound 改为 route rule 的 "action": "reject" 和 "action": "hijack-dns"。旧配置的 "outbound": "block" 会报找不到 outbound 或 deprecated。
1.12:部分 legacy DNS 选项与 special outbound 清理
DNS 服务器配置改为按类型声明("type": "https"、"type": "udp"),旧的 "address": "https://..." 写法进入弃用期。
迁移方法
- 官方迁移命令:
sing-box migrate -c old.json -w自动把能转的部分转掉,剩下的会在日志里提示。 - GUI 客户端:GUI.for.SingBox、Hiddify 一类客户端在升级内核时通常会自动迁移它们自己生成的配置,但不会迁移你手动导入的自定义配置。
- 订阅转换:用订阅转换服务生成 sing-box 配置时选对目标版本,或直接向机场要对应版本的订阅。
- 实在改不动:内核回退到配置对应的版本。版本回退相关的注意点见 sing-box 客户端教程。
三、DNS 规则错误
DNS 是 sing-box 配置里出错第二多的地方。
典型报错
initialize DNS server[0]: ...
parse dns rule[2]: ...
missing default dns server
dns server not found: xxx
常见原因
dns.rules里引用的server标签在dns.servers里不存在(拼写不一致)。- 没有设置默认 DNS 服务器(
dns.final或 1.12 后的默认规则),所有规则都不匹配时内核不知道用谁。 - DNS 服务器自己需要解析域名(比如
https://dns.google/dns-query),但没给它指定address_resolver(1.12 前)或domain_resolver,形成循环依赖。 - Fake-IP 相关:开了 fakeip 但
inet4_range没写,或 dns rule 里 fakeip 服务器没有限制到特定查询类型,导致所有域名都被 fake-ip,局域网设备和 NTP 不正常。 - DNS 监听端口(inbounds 里 type 为 direct 的 53 端口)被系统或其他程序占用。
处理顺序:先确认每个 dns.rules[].server 都能在 dns.servers[].tag 里找到;给远程 DoH / DoT 服务器配一个 UDP 直连 DNS 做解析器;确认有一个兜底的默认服务器。分流不正常但启动成功的问题,参考 DNS 泄漏说明。
四、TUN 权限
报错样例
start inbound/tun[tun-in]: configure tun interface: operation not permitted
create tun: ... Access is denied
TUN 需要创建虚拟网卡,必须有管理员 / root 权限。
- Windows:以管理员运行 sing-box 或 GUI 客户端。GUI.for.SingBox 有「以管理员身份运行」选项;也可以用任务计划程序以最高权限自启。Windows 上 sing-box 用 wintun 驱动,缺 wintun.dll 时报找不到文件,把 wintun.dll 放到内核同目录。
- macOS:GUI 客户端会请求安装网络扩展,在「系统设置 → 隐私与安全性」允许。命令行用
sudo sing-box run。 - Linux:
sudo sing-box run -c config.json,或sudo setcap cap_net_admin,cap_net_bind_service=+ep $(which sing-box)后普通用户运行。 - Android / iOS:由系统 VPN 权限控制,首次开启时弹窗允许即可,不涉及配置。
TUN 的 auto_route、strict_route 与系统其他 VPN 的冲突会表现为启动成功但没网,见 TUN 模式问题。
五、其他常见报错
| 报错片段 | 含义 | 处理 |
|---|---|---|
outbound not found: xxx | 规则引用了不存在的 outbound tag | 核对 tag 拼写 |
duplicate outbound tag | 两个 outbound 同名 | 改名 |
address already in use | inbound 端口被占 | 换端口或结束占用进程 |
parse outbound[3]: ... unknown transport type | 节点 transport 写法不被当前版本支持 | 查该版本文档 |
tls: failed to verify certificate | 服务器证书无效或系统时间错 | 校时;确认 server_name;自签证书才用 insecure |
uTLS ... not supported | 编译版本不含 uTLS | 换带 with_utls 标签的构建 |
missing tag | inbound / outbound 没写 tag | 补 tag |
platform ... not supported | 构建版本不支持当前平台功能(如 Android 的 process_name) | 删掉该规则 |
构建标签(build tags)决定了内核包含哪些功能:with_quic、with_utls、with_clash_api、with_gvisor 等。从 GitHub Releases 下载的标准版本包含常用标签;自己编译或某些精简发行版可能缺功能,报错「not included in this build」时换标准版本。
六、怎么看日志
- 命令行:
sing-box run -c config.json日志直接输出到终端。配置里:
"log": { "level": "debug", "output": "box.log", "timestamp": true }
- GUI.for.SingBox:首页的日志区域或「日志」页。
- Hiddify:设置 → 日志。
- Karing:诊断 → 内核日志。
- sing-box 官方 Android / iOS App:首页「Logs」。
启动失败的原因一定在日志最后几行,通常以 FATAL 开头。启动成功但运行异常的,把 level 调到 debug 能看到每条连接的匹配过程。
七、GUI 客户端特有的坑
GUI 客户端在内核之上又加了一层,有些错误其实不在配置本身:
- 客户端和内核版本不匹配。客户端自带的配置模板针对某个内核版本生成,手动替换成更新或更旧的内核后模板就不兼容。客户端设置里查看内核版本,用客户端自己的「更新内核」功能,不要手动替换文件。
- 订阅节点与模板混合。客户端把订阅节点注入模板时,节点里带了当前内核不支持的字段(比如某些新 transport 类型),整份配置报错。更新内核或在订阅转换时去掉该类节点。
- 多份配置互相覆盖。导入了多个配置文件,客户端实际运行的是另一份。确认当前激活的是哪一份再改。
- 日志被截断。客户端界面的提示只显示第一行,看不出完整原因。到客户端的日志文件目录看完整输出。
排查顺序
sing-box check -c config.json,看报错类型。- JSON 语法错 → 校验器定位,去掉尾逗号和注释。
- unknown field / deprecated →
sing-box migrate,或按版本章节手改。 - DNS 相关 → 核对 tag、默认服务器、解析器。
- TUN 权限 → 提权。
- 通过 check 但启动后退出 → debug 日志,看 rule_set 下载、端口占用。
- 以上都解决不了 → 用 GUI 客户端生成一份干净的最小配置能跑通,再把自定义部分一段一段加回去。
相关
sing-box 客户端教程 · GUI.for.SingBox 教程 · Hiddify 教程
常见问题
sing-box 报 decode config: json: ... 是什么问题?
JSON 语法错误:多了逗号、少了引号、括号不配对、或者写了注释。标准 JSON 不允许尾逗号和注释。用 sing-box check 或在线 JSON 校验工具定位行号。
报 unknown field geosite 或 geoip 怎么办?
sing-box 1.8 开始用 rule_set 替代 geosite / geoip,旧字段在新版本被移除。用 sing-box migrate 转换配置,或改成 rule_set 写法。
报 legacy ... is deprecated 或 removed?
你的配置用了被标记为旧版的选项(如 inbound 里的 sniff、domain_strategy,outbound 的 block / dns 类型)。按日志提示改到新位置,1.11 以后的版本会直接拒绝。
TUN 模式 sing-box 启动失败提示权限?
TUN 需要管理员 / root。Windows 以管理员运行,macOS 允许网络扩展并输入密码,Linux 用 sudo 或 setcap。
怎么看 sing-box 的日志?
命令行直接运行会输出到终端;GUI 客户端有日志页。配置里 log.level 设为 debug,log.output 指定文件,启动失败的原因在最后几行。
本文为信息整理与个人经验,不构成购买建议。机场政策与软件界面可能变化,以官方为准。发现过期内容请 联系纠错。