Skip to content

Guide

YAML 1.1 vs 1.2, and the Norway problem

The single most expensive YAML bug has a country code at the center of it.

By yamltojsonfree · Published · Updated

What the Norway problem is

In YAML 1.1, the unquoted words y, yes, on, n, no, and off are booleans — in upper case, lower case, or capitalized. So a list of country codes containing Norway — NO — quietly becomes false. Nothing errors. The document parses, the deploy succeeds, and somewhere downstream a country is missing from a list because a boolean can’t be a dictionary key or match a string comparison.

YAML 1.2, published in 2009, removed this: only true and false are booleans, and those six words are ordinary strings. It also dropped YAML 1.1’s other implicit conversions — 022 is no longer an octal for 18, and 12:30 is no longer a base-60 number worth 750.

The catch is that both versions are still in wide use, more than fifteen years later. The same file can therefore mean two different things depending on which tool opens it — which is exactly why the YAML to JSON converter on this site defaults to YAML 1.2 and flags every value in your document that would read differently under 1.1.

Every value that changes meaning

The same source, read by each version of the specification.

YAML sourceRead as YAML 1.2Read as YAML 1.1Safe form
country: NO"NO"falsecountry: "NO"
enabled: yes"yes"trueenabled: true
debug: off"off"falsedebug: false
mode: 0222218mode: "022"
start: 12:30"12:30"750start: "12:30"
version: 1.101.11.1version: "1.10"

Note the last row: 1.10 loses its trailing zero in both versions, because it’s parsed as a number. Version strings should always be quoted.

Which parsers read which version

You rarely choose a YAML version directly — you inherit one from whatever library your tooling happens to use. This is roughly how the ecosystem splits:

ParserVersionNotes
PyYAML (Python)YAML 1.1The default for most Python tooling, including Ansible.
ruamel.yaml (Python)YAML 1.2The maintained successor to PyYAML; 1.1 available as an option.
js-yaml v5 (JavaScript)YAML 1.2The engine this site uses. Earlier versions read 1.1.
go-yaml / sigs.k8s.io (Go)Mostly 1.2What Kubernetes uses; keeps a few 1.1 behaviors for compatibility.
SnakeYAML (Java)YAML 1.1The default in Spring Boot configuration loading.
libyaml (C bindings)YAML 1.1The base of many language bindings, PyYAML included.

The practical consequence: a file written on one side of that table and read on the other can silently change values. If your YAML is produced by Python and consumed by Kubernetes — a very common pipeline — it crosses the version boundary. The full code-level details are in the convert YAML to JSON in code guide.

How to write YAML that is safe in both

Three habits remove the entire class of bug. Quote any string that could be mistaken for something else — country codes, version numbers, values with leading zeros, and anything containing a colon. Write booleans only as true and false, never yes, on, or their relatives. And before a file crosses tools, run it through a converter or validator that reports version-dependent values — seeing your YAML as explicit JSON is the fastest way to catch a type you didn’t intend.

References