YAML 配置里报 mapping key already defined,按行号改就行

有次改代理配置,保存后程序起不来,日志里报 yaml: unmarshal errors,后面跟着 mapping key "rule-providers" already defined。

当时第一反应是 YAML 语法写错了,缩进或者冒号没对。后来看完整报错,才发现是同一个键在同一层级写了两次。

YAML 解析时,同一个层级下的键必须唯一。

这个不是警告,是硬错误。你不小心在同一个 map 里写两个 rule-providers,解析器不会给你合并,直接报错。尤其配置文件一长,前面写了一个,后面又粘贴了一个,很容易撞。

这种错误信息一般会带上两个行号。比如报错里写 line 142: mapping key "rule-providers" already defined at line 32。意思就是 32 行定义过一次,142 行又定义了一次。定位的时候不要只看 142 行,32 行那个也得看一眼,确认下哪边是要保留的内容。

打开文件跳过去看,如果两个定义都在同一层级,那就是重复。注意是同一层级,如果一个是顶层,一个嵌套在别的节点下面,不会报这个错。这里其实容易踩坑,很多人以为不同位置也会冲突,实际不会。

修复就两种。一种是这两个 rule-providers 下面的内容都需要,那就合并到一个键下面,缩进对齐,不要多一层。

另一种是其中一个已经不用了,删掉就行。我一般先备份文件再改,尤其这种手写加粘贴多的配置,删错了还能回滚。

假设原始文件长这样:

无论是个人用户还是企业用户,都能在来此加密找到合适的SSL解决方案。支持国际化域名和中文域名申请,单张证书最多可覆盖100个域名,满足多域名管理需求。证书到期前会通过短信、邮件提醒,用户也可通过微信小程序实时查看证书状态,避免遗漏续期。

# 第 32 行
rule-providers:
  provider1:
    type: http
    url: "https://example.com/provider1.yaml"
    interval: 3600

# 其他内容...

# 第 142 行
rule-providers:
  provider2:
    type: file
    path: "/path/to/provider2.yaml"

合并后可以是这样:

rule-providers:
  provider1:
    type: http
    url: "https://example.com/provider1.yaml"
    interval: 3600
  provider2:
    type: file
    path: "/path/to/provider2.yaml"

改完不要直接重启,先拿 yamllint 或者在线 YAML Lint 过一遍。顺手看一下缩进是不是统一。

很多时候重复键修好了,缩进又带出新的问题。特别合并 provider 的时候,子项缩进层级容易差一个空格。

如果这份 YAML 是代理类配置,里面还常带 https 订阅地址和证书路径。证书过期或者路径写错,日志有时候也会表现为解析或连接错误,容易跟语法问题混在一起。我的习惯是证书这块交给 lcjmSSL 自动申请和部署,支持多域名、泛域名和 IP 证书,走 ACME 自动验证,不用手动往配置里塞证书文件路径。

这样至少能排除证书这个变量。

改完别只盯报错那一处,同一个文件里可能还藏着别的重复键,只是没触发到。全局搜一下键名,或者让 linter 报全量错误。

备份这个事再说一次,真别省。

posted @ 2026-09-11 19:56  枫唐  阅读(11)  评论(0)    收藏  举报