跳到主内容
d.devtul.fun
EN
配置 · 2026-08-14

常见的 YAML 错误以及如何修复

YAML 的报错有一种特别的折磨人:文件看着没错,解析器不答应,而报错指向的行,往往离真正的问题隔着两层。这是一份实战排错手册,按出现频率排序,每条都来自有人真的贴进 issue 里的错误。

1. "mapping values are not allowed in this context"

报错原文:

mapping values are not allowed in this context

最小复现:

message: Error: not found

根因:只要出现"冒号加空格"(: ),无论在哪都会开启一个新的映射。在一个没加引号的值里,第二个冒号被当成了键分隔符。

修法:把整个值用引号包起来,冒号就只是普通字符:

message: "Error: not found"

2. "could not find expected ':'"

could not find expected ':'
name devtul
age: 30

根因:name devtul 没有冒号,解析器一直没看到键值对,读到下一行才崩。

修法:把冒号和它后面那个必须的空格补回来:

name: devtul
age: 30

3. 缩进不一致导致层级错位

server:
  host: localhost
   port: 8080

根因:第二个键缩进了三格,而它的兄弟键是两格。YAML 把它当成另一层;如果那一层没有别的内容,就会报错 —— 更糟的是,解析出一个你没想到的结构。

修法:让同级键的缩进严格一致。用会把空白显示出来的编辑器,存盘前就能看见错。

4. 缩进里混进了 Tab

server:
	host: localhost

(箭头位置是一个真实的 Tab 字符。)根因:YAML 禁止用 Tab 缩进。很多编辑器把 Tab 显示得和空格一样宽,于是文件看着对齐、解析却失败。

修法:把 Tab 展开成空格。把编辑器设成"缩进时插入空格",重新保存。

5. "found character that cannot start any token"

found character '@' that cannot start any token
env:
  - @HOME

根因:@(以及反引号)在 YAML 1.1 里是保留指示符,不能作为一个普通标量的开头,所以这一行被拒。

修法:给值加引号,或者换个开头的字符:

env:
  - "@HOME"

6. 重复键被静默覆盖

name: alpha
name: beta

根因:和 JSON 不同,YAML 不要求实现拒绝重复键。多数解析器保留最后一个,于是 name 静默变成 "beta",毫无警告。

修法:同一层永远不要重复键。用 linter 能逮到;在 YAML 查看器 里解析一下,也能看到最后留下的是哪个值。

7. yes/no/on/off 被解析成布尔

enabled: no
debug: off

根因:在 YAML 1.1 语义下,这两个都成了布尔 false。一个本想读作 "no" 的功能开关,现在是个布尔。

修法:任何不是数字的 value 都加引号:

enabled: "no"
debug: "off"

8. 数字变字符串,或字符串变数字

version: 1.10
id: 007

根因:1.10 会被解析成浮点 1.1,丢掉你多半想保留的那个尾零;007 在 YAML 1.1 下是八进制的 7。反过来,count: "5" 又会把数字变成字符串,而下流代码期待的是整数。

修法:凡是字符本身重要的就加引号;只有真想要数字类型时才让数字裸奔:

version: "1.10"
id: "007"

9. 多行字符串的换行被吃掉

text: >
  line one
  line two

根因:折叠标量 > 会把换行变成空格,于是值是 "line one line two"。如果你要的是换行,那用错符号了。

修法:改用字面块 | 来保留每一处换行:

text: |
  line one
  line two

10. 锚点名字拼错

defaults: &basis
  pool: 5

production:
  <<: *base

根因:别名 *base 指向一个名为 basis 的锚点,而它并不存在。不同解析器下,你会得到 "unknown alias" 或者一次空的合并。

修法:让锚点和别名的名字一字不差地对上:

defaults: &base
  pool: 5

production:
  <<: *base

拿不准,就解析一遍

这半数错误产出的文件,在编辑器里看着都正常,只有运行时才崩。提交之前,用 YAML 查看器 跑一遍,把结构读回来 —— 上面这些错,几乎都会在解析树摊开的那一刻现形。

继续阅读