Write a list of country codes in YAML and leave NO unquoted, and an older parser hands back the boolean false. The country code for Norway is a reserved word, and nothing in the file looks wrong.
This is the price of a format that guesses types from how a value is written. YAML is pleasant to read and it makes decisions on your behalf, and the decisions it makes are the source of nearly every YAML bug.
Which values change type?
The unquoted ones that look like something else.
| Written | Read as | Intended |
|---|---|---|
| no | false | "no" |
| yes, on, off | booleans | the words |
| 1.10 | the number 1.1 | version 1.10 |
| 22:22 | 1342 in older parsers | a time |
| 08 | an error in older parsers | the number 8 |
| null, ~ | nothing | the word |
The sexagesimal case is the strangest. Older YAML read colon-separated digits as base 60, so a time or part of a MAC address became a single large integer — and the newer revision of the specification removed the behaviour, while parsers implementing the older one are still in wide use.
The defence is quoting. A quoted scalar is a string and stays one, and quoting anything that is meant to be text regardless of how it looks costs nothing.
Why is indentation so fragile?
Because it carries the structure, and tabs are forbidden in it. YAML allows spaces only for indentation, so a tab pasted from an editor produces an error that points at a line looking identical to the one above it.
Nesting depth is meaningful to the character, which makes a misaligned block a silently different document rather than an error — a key indented two spaces too far becomes a child of the wrong parent, and the file parses.
This is the argument for running a formatter over a config before committing it. Reindenting from the parsed structure proves the structure is what you thought, which reading cannot.
What are anchors for?
Reusing a block without repeating it. An anchor names a node and an alias refers back to it, so a shared set of defaults can be defined once and pulled into several places.
It is genuinely useful in a long deployment file and it has a sharp edge: aliases can nest, and a small file of nested aliases can expand into an enormous structure in memory. That expansion is a known denial-of-service shape, which is why parsers handling untrusted input restrict it.
The practical guidance is unchanged for a file you wrote yourself. For a file from somewhere else, expansion is a reason to be careful about what parses it.
Comments survive none of these conversions. YAML, TOML and INI all allow them and JSON does not, so converting a commented config to JSON silently discards every explanation in it — which matters most for exactly the files that needed explaining.
What do the alternatives fix?
TOML fixes the guessing. Types are explicit, strings are quoted, and the grammar is small enough that two implementations agree — the trade is that deep nesting is more verbose to express.
INI fixes nothing because there is nothing to fix against: it has no specification at all. Whether a semicolon or a hash starts a comment, whether sections nest, and what a repeated key means are all decided by whichever library is reading it.
Environment files are in the same position. There is no standard for quoting, escaping or multi-line values, so a .env file that works with one loader can fail with another — which is why keeping values simple matters more there than anywhere else.
XML is the verbose end and the unambiguous one. Nothing is inferred, everything is delimited, and the cost is that the delimiters are most of the file.
Does formatting a config change it?
It should not, and that is the test. A formatter parses the file and prints the structure back out, so if the output differs in meaning rather than in layout, the file did not mean what it looked like.
That makes reformatting a cheap way to check a hand-edited deployment file, a server config or a schema before it reaches anything that will act on it. The diff shows you what the parser saw.
It also normalises the things that cause noisy diffs later — quoting style, key spacing, indentation width — so the next real change stands out on its own.
Questions people ask
Can I comment a JSON config anyway? Only by adding a key nobody reads, which is the practice the format was designed to discourage. Convert to a format that supports them instead.
Is JSON valid YAML? For the current revision, yes: YAML is a superset. Older parsers have exceptions.
Should I quote every string? Quote anything that could be read as a number, a boolean, a date or null. Ordinary words are safe.
Why did my multi-line string lose its line breaks? The folded style joins lines. The literal style keeps them, and the two are one character apart.
Which format for a new project? TOML if the structure is shallow and you want no surprises; YAML if it is deep and humans will edit it constantly.
Reformat before you trust it. The YAML formatter proves what the parser sees, YAML to JSON and JSON to YAML move between them, and the TOML, INI, XML, env, Docker Compose, nginx, Apache and GraphQL formatters each know the shape of their own file.