Country codes turning into false and version numbers into floats are real production bugs.
Implicit typing is convenient until a value that should be a string happens to look like something else. The infamous case is the Norway problem: a list of country codes where NO becomes false.
The rules depend on the YAML version the parser implements. Many popular parsers (PyYAML, older libyaml-based tools, Ruby's Psych, many Go v2 users) follow YAML 1.1, where:
yes,no,on,off,y,nand their capitalised forms are booleans;012is octal (10),0b101binary, and1_000is 1000;1:30is a sexagesimal integer, 90;2026-10-17becomes a date object.
YAML 1.2's core schema is stricter: only true/false are booleans, octal needs 0o, and sexagesimals and implicit dates are gone. Parsers implementing it include ruamel.yaml, Go's yaml.v3 (mostly), js-yaml 4 and the yaml npm package.
Some surprises exist in both: 1e3 is a float, .5 is a float, null and ~ are null, and 3.10 is the float 3.1.
How to stay safe:
- Quote any string that could be read as something else: versions, codes, zip codes, times, IDs.
- Validate the loaded data against a schema so a wrong type fails loudly.
- Know which YAML version your tool's parser implements.
Example
# key YAML 1.1 (PyYAML) YAML 1.2 core schema
country: NO # False 'NO'
switch: on # True 'on'
answer: yes # True 'yes'
mode: 0755 # 493 (octal) 755
time: 1:30 # 90 (base 60) '1:30'
date: 2026-10-17 # date(2026,10,17) '2026-10-17' (ruamel.yaml still gives a date)
python: 3.10 # 3.1 3.1
build: 1e3 # '1e3' (1.1 needs a dot) 1000.0
# safe in every parser:
country_q: "NO"
version_q: "3.10"Remember
- YAML 1.1 parsers treat yes/no/on/off as booleans and 012 as octal
- YAML 1.2 core only has true/false and 0o octal
- Quote codes, versions, times and IDs; validate types after loading
Watch out for
- Assuming your parser follows YAML 1.2; PyYAML and many tools still implement 1.1.