把订阅失败当成一次普通 HTTP 请求,而不是客户端玄学。客户端刷新订阅时只做三件事:请求 URL,拿到正文,把正文解析成自己的配置格式。任一环失败,界面都可能只显示「更新失败」「timeout」「parse error」或空列表。
排查时先保留原始订阅 URL,不要连续换 App、换 DNS、换格式。一次只改一个变量,才能判断 403、404、429、5xx、HTML 登录页、YAML 解析错误和本机缓存分别来自哪里。
##把错误归到哪一层?
| 表现 | 更可能层级 | 第一证据 | 做动作 |
|---|---|---|---|
timeout、一直转圈 | DNS、TLS、当前 VPN 状态、服务端无响应 | 请求没有得到完整正文 | 断开当前 VPN 状态,换浏览器或命令行请求 URL |
403 / 401 | token、账号权限、User-Agent、服务端访问策略 | 响应状态不是 200 | 记录时间和域名,让提供方查请求日志 |
404 | 路径不存在、订阅被重置、短链失效 | URL 最终路径报不存在 | 重新生成订阅 URL,别继续刷新旧二维码 |
429 | 请求过快、token 被限流 | 多次刷新后失败更明显 | 停止反复更新,等限流窗口结束或换 token |
5xx | 服务端或网关故障 | 多设备同时间失败 | 等服务端恢复,客户端设置先别动 |
| 更新完成但列表为空 | 正文格式错、筛选器隐藏、返回空文本 | 正文第一行和节点数量 | 保存响应正文,再看分组和搜索框 |
parse error / YAML 报错 | 缩进、字段、provider 引用、内核不兼容 | 日志里有行号或字段名 | 用目标客户端格式重新导出 |
这张表的重点是先分层。HTTP 状态异常时,不要先清客户端缓存;正文格式错时,不要先改 DNS;列表为空时,不要立刻重装 App。
订阅 URL 返回什么才算有效?
macOS / Linux 可以先用 curl 保存响应:
curl -L -A "clash-verge" "你的订阅URL" -o /tmp/subscription.txt
Windows PowerShell 可以这样保存:
Invoke-WebRequest -MaximumRedirection 5 -Headers @{"User-Agent"="clash-verge"} -Uri "你的订阅URL" -OutFile "$env:TEMP\subscription.txt"
打开文件只看前三行,不要先研究整份配置。
| 正文特征 | 可能格式 | 更适合的客户端 | 异常判断 |
|---|---|---|---|
proxies:、proxy-groups:、proxy-providers: | Clash / Mihomo YAML | Clash Verge Rev、FlClash、OpenClash | 给 v2rayN 或 sing-box 可能失败 |
{ "outbounds" 或 JSON 顶层配置 | sing-box JSON | sing-box、SFA、Hiddify、Karing | 给 Clash 通常不能直接解析 |
多行 vmess://、vless://、trojan://、ss:// | URI 列表 | v2rayN、v2rayNG、部分 iOS 客户端 | 字段新旧要看核心支持 |
| 一整段 Base64 | V2Ray 订阅包装 | v2rayN、v2rayNG | 先本地解码,不要发到陌生网页 |
{ "version": 1, "servers": ... } | Shadowsocks SIP008 | 支持 SIP008 的客户端 | 缺 servers 或 HTTPS 交付异常会失败 |
<html>、登录页、公告页 | 网页 | 不是订阅正文 | 客户端无法生成节点 |
| 空文本 | 服务端返回空 | 不是有效订阅 | 查 token、账号状态和服务端日志 |
MDN 对 User-Agent 的定义能解释一个常见现象:浏览器、Clash、sing-box、v2rayN 发出的请求头不同,订阅端可能据此返回不同正文。浏览器打开正常,不等于目标客户端拿到的也是同一份配置。
Clash / Mihomo 客户端要看哪些字段?
Clash Verge Rev、FlClash、OpenClash 这类 Mihomo 客户端最常见的订阅失败,是拿到的不是 Clash/Mihomo YAML,或者 YAML 里 provider 引用不完整。
最小检查点有 4 个:
- 顶层有
proxies或proxy-providers。 - 有
proxy-groups,且组里引用的节点名或 provider 名存在。 - 有
rules,并且缩进没有被 Tab、中文空格或聊天软件改坏。 - 使用
proxy-providers时,type: http的 provider 能单独下载。
Mihomo 官方 proxy-providers 文档里,HTTP provider 至少会涉及 type、url、path、interval、proxy、health-check 等字段。实际排错时,url 是否可达、path 对应缓存是否损坏、proxy 是否让 provider 更新请求走错路径,比反复点刷新更重要。
| 日志或界面信号 | 重点检查 | 处理办法 |
|---|---|---|
proxy provider 更新失败 | provider 的 URL、DNS、下载路径 | 单独请求 provider URL,必要时清对应缓存 |
proxy-groups 空 | use 名称、节点筛选、provider 返回内容 | 对照 provider 名称大小写和筛选规则 |
| YAML 行号报错 | 缩进、冒号、列表符号 | 用纯文本编辑器定位行号,不从聊天窗口复制 |
| 旧配置能用,新配置不能 | 内核字段支持、订阅端输出变化 | 升级客户端与内核,或要求订阅端回退格式 |
Shadowrocket 和 Stash 为什么 Safari 正常 App 仍失败?
iOS 上的第一步是 Safari,但 Safari 只负责看最终响应。Safari 打开网页,不代表 Shadowrocket 或 Stash 能解析这个网页。
Shadowrocket、Stash 这类客户端在订阅正文为空、格式不兼容或返回错误页时,不会凭空补出节点列表。订阅更新后空白时,先回到 URL、HTTP 状态和正文格式,而不是只看 Safari 能不能打开网页。
iOS 还会叠加系统 VPN 状态。Apple Platform Security 的 VPN 文档说明,VPN App 会进入系统级网络路径;当当前隧道处在异常状态时,订阅请求可能继续走一条坏路径。排查顺序建议是:
- 断开当前 VPN 状态。
- 用 Safari 打开订阅 URL,看最终正文。
- 若 Safari 返回配置文本,再回 App 删除远程配置并重新添加。
- 若只有远程规则失败,暂停规则源,只更新订阅本体。
- 若 Wi-Fi 正常、蜂窝数据失败,再看 iOS 蜂窝数据权限和 DNS。
Stash、Loon、Surge 这类 iOS 客户端也有远程规则、模块、策略组等附加内容,让订阅本体独立成功,再恢复规则源,否则一个 GitHub raw 或远程规则超时会被误判成订阅失败。
v2rayN / v2rayNG 为什么更新后列表为空?
v2rayN 和 v2rayNG 常见问题不是「下载不到」,而是入口和格式错位。单条分享链接与订阅 URL 在客户端里不是同一个入口。
| 输入开头 | 内容类型 | 正确处理 | 空列表原因 |
|---|---|---|---|
vmess:// | 单条 VMess | 从剪贴板导入服务器 | Base64 残缺或备注截断 |
vless:// | 单条 VLESS | 从剪贴板导入服务器 | Reality、SNI、path、pbk、sid 字段缺失 |
trojan:// | 单条 Trojan | 从剪贴板导入服务器 | TLS / SNI 参数不完整 |
ss:// | 单条 Shadowsocks | 从剪贴板导入服务器 | 加密方式、端口、密码被改写 |
https:// | 在线订阅 | 加入订阅分组后更新 | 当作单条链接导入、返回网页或格式错 |
v2rayN 官方 GitHub Release 页面是检查客户端版本的入口。若订阅里使用新的 Xray、sing-box 或 Reality 字段,旧客户端或缺核心的安装包可能只能导入一部分条目。
列表为空还要排除视图误判:清空搜索框,切到「全部」或对应订阅分组,按更新时间排序。日志显示新增数量大于 0,而列表仍为空,常常是筛选器把条目藏住了。
sing-box / Hiddify / Karing 哪些格式不能混用?
sing-box 官方配置文档明确以 JSON 配置为核心。Hiddify、Karing、SFA 等客户端虽然可能支持多种导入入口,但排错时仍要确认当前 URL 返回的是目标客户端能吃的格式。
Clash YAML 与 sing-box JSON 的差异不是文件后缀那么简单。Clash 的 proxy-groups、rules、proxy-providers 不能直接等同于 sing-box 的 outbounds、route、rule_set。把 Clash YAML 改名成 .json 没有意义。
sing-box 还有版本迁移问题。官方 migration 文档会记录旧字段替换、新字段启用和规则结构变化。若订阅端输出的 JSON 使用了新写法,而客户端内置核心较旧,就会出现导入失败或启动失败。
处理顺序,让订阅端输出明确的 sing-box JSON;再用客户端导入;最后看日志里的具体字段。不要在同一轮里同时换 Clash 格式、V2Ray 格式和 sing-box 格式。
什么时候该换客户端,什么时候该换订阅源?
换客户端的条件很窄:同一条 URL 在浏览器和命令行拿到有效正文,在同类客户端里能正常解析,只有当前客户端报错,而且日志指向本地缓存、权限或版本问题。这时升级、清缓存或临时换客户端才有价值。
换订阅源的信号更明确:多台设备都拿到 403、404、429、5xx、HTML、空文本;同一账号在不同客户端拿到互相不兼容的正文;提供方无法固定 Clash / sing-box / V2Ray 输出格式。此时继续折腾客户端,只是在掩盖源头问题。
多人或多设备共用配置时,最容易乱的是「每个人复制到的都不是同一种链接」。有人拿 Clash YAML,有人拿 VLESS 单条链接,有人拿到登录页截图。可以把兼容 Clash / Singbox / V2Ray 的订阅作为统一来源,再分别导出目标客户端格式;排查时至少能确认问题不来自链接来源混乱。
修好以后怎么验收?
| 验收项 | 合格信号 | 仍有问题的信号 |
|---|---|---|
| URL 响应 | 200,正文第一行是目标格式 | 403、404、429、5xx、HTML、空文本 |
| 客户端导入 | 节点数量不为 0,分组显示正常 | 更新完成但列表为空 |
| 日志 | 没有 provider、parse、core 字段错误 | 仍有行号、字段、下载失败 |
| 网络状态 | 断开与连接后都能手动刷新 | 只有某一种网络能刷新 |
| 重启验证 | 关闭再打开客户端后配置仍在 | 依赖旧缓存或临时状态 |
至少做两次更新:一次在断开当前 VPN 状态下更新订阅,一次在正常使用状态下手动刷新。两次都能拿到同样的节点数量,才说明 URL、格式、缓存和本机网络路径基本完整链路。
最后保存一条排错记录:客户端名称、客户端版本、系统版本、订阅域名、HTTP 状态、正文格式、失败时间、修复动作。下次同域名再出 403 或 429,就不用从 App 权限重新猜。