Clash 订阅更新失败或解析报错:链接格式、User-Agent 与 YAML 自查清单
订阅拉取失败、导入后节点为空或提示解析错误时,按链接有效性、请求头、返回内容格式与 YAML 缩进逐项排查。
1. 错误分层:先记录失败发生在哪一步
先保留当前能用的配置,再手动更新一次订阅,记录更新时间和完整错误。订阅更新依次经过域名解析、HTTPS 连接、HTTP 响应、内容解析和配置加载。前一层失败,修改后一层的规则通常没有作用。
桌面客户端先打开订阅或配置列表,确认正在更新的是哪一条记录,再查看应用日志或内核日志。界面名称随客户端而变,不要把“配置文件更新成功”当成“节点提供器更新成功”。两者可能来自不同地址,也有独立缓存。
| 错误或现象 | 优先检查 | 下一步操作 |
|---|---|---|
no such host | 订阅域名解析 | 检查系统 DNS 与当前网络 |
connection refused | 目标端口或本地代理端口 | 确认错误中的主机与端口 |
401、403 | 授权、访问策略、请求头 | 重新获取订阅地址并核对响应正文 |
429 | 请求频率限制 | 停止连续重试,遵循服务端重试时间 |
yaml: 或 unmarshal | 返回格式、字段类型、缩进 | 保存原始响应,在本地检查 |
| 更新成功但节点为空 | 配置类型、提供器、过滤条件 | 区分完整配置与节点列表 |
2. 链接格式:复制原始订阅,不复制登录页面
从服务方后台重新复制
- 登录服务方后台,选择明确标注 Clash 或兼容当前内核的订阅格式。
- 使用复制链接功能,不从聊天软件的截断预览中拼接地址。
- 检查开头是否为
https://,末尾是否混入空格、换行、中文句号或右括号。 - 保留完整查询参数。不要随意删除
?后的内容,也不要把&分隔的参数截掉。
网页源码中的 & 是 HTML 实体写法,实际 URL 的参数分隔符应是 &。若复制出的地址真的含有字符序列 &,后续参数可能被错误命名。通过后台复制按钮重新取得地址,比手工替换更稳妥。
clash:// 一类地址可能只是调用应用的导入指令,不是可直接下载的 HTTPS 订阅。浏览器地址栏中的用户中心、订单详情和订阅说明页,也不能当作配置地址。浏览器能够打开某个页面,只说明页面可访问,不说明它返回了 YAML。
检查登录状态与重定向
浏览器已有登录 Cookie 时,下载可能正常;客户端没有这份 Cookie,可能得到登录页或拒绝响应。合法的订阅接口通常依靠链接令牌等接口授权机制。不要把浏览器 Cookie 粘到来源不明的脚本里,应按服务方文档重新生成客户端可用地址。
遇到 301、302 或 307,确认最终地址仍属于预期服务。若重定向到登录页面、验证页面或已经失效的域名,应先解决接口访问问题,而不是调整 YAML 缩进。
3. HTTP 响应:保存状态码、响应头和原始正文
Linux、macOS 可在本地终端使用 curl。Windows PowerShell 请明确调用 curl.exe,避免旧环境中的同名别名。以下命令把地址交给交互输入,避免把完整订阅直接写进命令历史;输入时仍应注意屏幕可见性。
# Linux / macOS:在个人目录下建立受限的排查目录
mkdir -m 700 subscription-check
cd subscription-check
umask 077
read -r -s -p '粘贴订阅 HTTPS 地址:' SUB_URL
printf '\n'
curl --location --max-redirs 5 \
--proto '=https' --proto-redir '=https' \
--connect-timeout 10 --max-time 30 \
--dump-header response-headers.txt \
--output response-body.txt \
--write-out 'HTTP %{http_code}\n' \
"$SUB_URL"
unset SUB_URL
10 秒是连接超时,30 秒是整次请求上限,都只是本次诊断参数,不是性能承诺。命令没有使用 --fail,因此服务器返回错误时也会保留正文,便于区分授权提示和配置数据。若命令报网络错误,先处理该错误;显示 HTTP 000 不代表服务端发送了状态码 000。
- 200:继续看正文。登录页、验证页面和错误 JSON 也可能返回 200。
- 401 / 403:检查令牌、订阅状态、访问限制和响应说明。403 本身不能证明一定是 User-Agent 问题。
- 404 / 410:检查路径是否过期、域名是否迁移,重新从后台获取地址。
- 429:若有
Retry-After,按其指示等待。不要反复点更新。 - 500 / 502 / 503:保留时间与状态码,稍后再试;客户端重装一般不能修复服务端错误。
在本地文本编辑器中打开 response-body.txt。以 <!DOCTYPE html> 或 <html 开头,通常是网页;以 JSON 错误对象开头,应先读错误字段。Content-Type 可作参考,但某些接口会把 YAML 标成普通文本,不能只凭响应头判定内容有效。
4. User-Agent:只做有依据的请求对照
部分订阅接口会根据 User-Agent 选择输出格式,另一些要求显式的格式参数。浏览器返回节点分享链接,而客户端返回 YAML,可能是同一接口的不同输出策略。应先查看服务方支持的客户端说明,不要随机尝试浏览器标识。
在上述终端会话中重新输入订阅地址后,可用以下命令做一次对照。mihomo 只是测试标识,不保证与某个图形客户端实际发送的请求头相同,也不保证所有接口都识别它。
read -r -s -p '粘贴订阅 HTTPS 地址:' SUB_URL
printf '\n'
curl --location --max-redirs 5 \
--proto '=https' --proto-redir '=https' \
--connect-timeout 10 --max-time 30 \
--user-agent 'mihomo' \
--dump-header response-headers-ua.txt \
--output response-body-ua.txt \
--write-out 'HTTP %{http_code}\n' \
"$SUB_URL"
unset SUB_URL
对照两份正文的顶层字段与状态码。如果只有指定请求头后才得到兼容配置,检查客户端是否提供“订阅请求 User-Agent”设置。全局订阅导入与 proxy-providers 下载是两条不同路径,修改其中一处不一定影响另一处。只有当前内核文档明确支持时,才在对应提供器配置中设置请求头。
5. 内容格式:完整配置、提供器与分享链接不能混用
Clash 配置不是“任何节点文本”的统称。常见返回内容有三类,导入位置必须对应。文件扩展名为 .yaml 也不能保证内部结构符合内核要求。
| 内容类型 | 常见结构 | 正确处理 |
|---|---|---|
| 完整 Clash 配置 | proxies、proxy-groups、rules 等字段 | 作为配置文件导入,并检查其引用关系 |
| 节点提供器文件 | 通常以 proxies: 为顶层节点列表 | 由主配置的 proxy-providers 引用 |
| 分享链接或编码文本 | ss://、vmess:// 等,或整段 Base64 文本 | 选择服务方的 Clash 输出,或使用明确支持该格式的本地导入功能 |
完整配置也可以通过 proxy-providers 获取节点,不一定内嵌 proxies。因此看到内嵌列表为空,不能直接断言订阅没有节点;应继续检查提供器下载是否成功、策略组是否通过 use 引用了正确名称。
若服务方只返回编码后的分享链接,解码后仍不一定是 Clash 配置。不要把解码文本直接改名为 config.yaml。优先使用服务方提供的对应格式,避免把订阅凭据交给陌生转换接口。
6. YAML 解析:先修首个错误,再查字段兼容性
缩进、引号与字段类型
YAML 缩进使用空格,不使用 Tab。同一层级保持一致,例如每层两个空格。出现“第 18 行附近解析失败”,应同时检查第 17 行:缺失的引号、冒号或错误缩进,经常到下一行才被解析器发现。
- 冒号:键值之间使用半角
:,其后通常保留一个空格。 - 列表:项目使用半角
-加空格,列表所属字段要有正确缩进。 - 字符串:名称包含“冒号加空格”时用引号包住,避免被识别为映射结构。
- 类型:端口等数值字段按内核要求填写整数;布尔值使用
true或false,不要写成中文开关。 - 重复键:不要重复定义两段顶层
rules或proxy-groups。部分解析器会拒绝,另一些可能覆盖前面的值。
下面仅演示策略组和规则的结构,不包含远端节点,也不是可替代订阅的完整配置。诊断时不要覆盖正在使用的文件。
proxy-groups:
- name: "手动选择"
type: select
proxies:
- DIRECT
rules:
- "DOMAIN-SUFFIX,example.com,手动选择"
- "MATCH,手动选择"
规则末尾的策略名称必须与已定义的策略组或内置策略一致。把组名从“手动选择”改成其他名称时,也要同步修改规则中的引用。YAML 语法通过,只说明文本能解析,不说明代理协议、字段组合和名称引用都有效。
使用实际运行的内核测试
mihomo 可在本地执行配置测试。先通过 mihomo -v 记录版本,再运行下面的命令;文件名对应保存在当前目录的待测配置。
mihomo -v
mihomo -t -f ./config.yaml
尽量使用图形客户端实际调用的内核版本。测试另一份较新的独立内核,只能说明那份内核是否接受配置,不能证明应用内置内核也兼容。提供器、规则集和地理数据库等外部依赖仍需结合启动日志检查。
若提示不支持某种代理类型或字段,先确认订阅输出目标。Clash、Clash Meta(mihomo)及不同分支的配置能力并不完全相同。不要通过删除协议必要字段来强行消除报错;应改用兼容输出或在确认客户端支持后更新内核。
7. 节点为空与网络失败:分开验证下载和加载
更新成功,为什么列表仍然为空?
- 确认激活配置:更新的是配置 A,正在运行的可能仍是配置 B。更新后检查当前配置名称和加载日志。
- 检查提供器:主配置下载成功后,节点提供器仍可能因 DNS、授权或网络错误而失败。
- 检查筛选:
filter、exclude-filter或界面搜索条件可能排除了全部节点。先在副本中移除筛选,再观察结果。 - 检查策略组引用:提供器名必须与策略组的
use一致;仅声明提供器不等于所有策略组都会显示其节点。 - 区分列表为空与测试超时:节点已出现但延迟测试失败,属于连接或测试路径问题,不再是“订阅没有解析出节点”。
系统代理、TUN 与本地端口
订阅请求是否经过代理,取决于客户端自己的更新设置和运行环境。启用系统代理不保证后台更新器会使用它;启用 TUN 也不能修复失效令牌或错误 YAML。先确认请求走直连还是现有代理,再一次只改一个设置。
若错误指向 127.0.0.1:7890,检查实际监听端口是否为 7890,以及内核是否正在运行。7890 只是常见示例,不是所有客户端的固定值。内核启动失败后,更新器若继续依赖这个本地代理,就会形成“配置没加载,订阅也拉不下来”的循环。可在客户端支持的情况下临时改为直连更新,保留原设置以便恢复。
若报 x509、证书过期或证书尚未生效,先同步系统日期、时间与时区,再检查是否处于需要网页登录的公共网络。不要把关闭证书验证作为长期解决办法。DNS 失败时先检查系统解析和订阅域名,不要同时大改 DNS、TUN、规则和节点协议,否则很难判断是哪一项产生作用。
8. 恢复验证:连续两次确认,再恢复自动更新
- 手动更新一次,确认响应正文确为预期配置,不再出现登录页或接口错误。
- 加载配置,确认日志没有解析错误,提供器能够完成下载,策略组出现预期节点。
- 选择一个节点建立正常连接。节点可用性与订阅更新结果分别记录,不用一个“成功”状态替代全部验证。
- 经过合理间隔再次更新,确认不是依靠旧缓存暂时显示成功,然后恢复原先的自动更新周期。
仍未解决时,向服务方提交客户端名称、实际内核版本、系统平台、出错时间、HTTP 状态码和脱敏后的错误行。不要发送完整令牌、节点密码或整份原始配置。删除本地排查文件前,先保留不含凭据的结论;响应头也可能包含 Cookie 或带令牌的重定向地址,应一并按敏感数据处理。
需要重新选择客户端,先查看客户端对比;需要了解规则、策略组与提供器的区别,可查看概念速查。恢复顺序保持不变:链接有效、响应正确、格式兼容、加载成功,最后才是连接测试。