Most YAML bugs come from three places: aggressive type coercion of unquoted values (the Norway problem, versions that lose digits), the ban on tab characters for indentation, and inconsistent indentation that silently changes structure. YAML is popular because it reads cleanly and supports comments, but that friendliness is bought with a grammar that tries to guess what you meant, and its guesses are sometimes wrong. This article walks through the traps that actually break real configuration files and gives one defensive habit that removes almost all of them.
What is the Norway problem?
The Norway problem is the most famous YAML gotcha: under older YAML rules, the unquoted value no is interpreted as the boolean false, so a country code for Norway silently turns into a boolean. Consider a list of country codes:
countries:
- GB
- US
- NO
- SE
A YAML 1.1 parser reads NO not as the string "NO" but as false, because yes, no, on, off, true, and false are all recognised as booleans in that version. Your list of four strings becomes a list of three strings and one boolean, and code downstream that expected text either crashes or behaves strangely. The fix is to quote the value:
countries:
- GB
- US
- "NO"
- SE
Now every element is unambiguously a string. The Norway problem is the poster child for a broader lesson: YAML coerces unquoted scalars into types based on how they look, and any value that happens to resemble a boolean or number is at risk.
Why do version numbers and other values lose data?
Unquoted values that look like numbers are parsed as numbers, which quietly damages version strings, ZIP codes, and identifiers with leading zeros. A version like 1.10 is a classic casualty. Written without quotes it is parsed as a floating-point number, and since the trailing zero of a float is not significant, 1.10 becomes 1.1:
version: 1.10 # parsed as the number 1.1 — zero lost
version: "1.10" # parsed as the string "1.10" — correct
The same class of bug hits several common values. The table below shows what happens to unquoted scalars that were meant to be text.
| You wrote | Unquoted, YAML sees | Quote it as |
|---|---|---|
1.10 |
The number 1.1 | "1.10" |
01234 |
A number, possibly octal | "01234" |
NO |
The boolean false | "NO" |
yes |
The boolean true | "yes" |
3:30 |
A base-60 number in some parsers | "3:30" |
~ |
null | "~" |
Every row is a real value that a person would reasonably type expecting it to stay as text. A ZIP code like 01234 loses its leading zero or is misread as octal; a time like 3:30 can be interpreted as a sexagesimal number in some parsers; a lone tilde becomes null. The pattern is consistent: if a scalar could be read as a number, a boolean, or null, an unquoted YAML value will be. The remedy is equally consistent, which is to quote anything whose type is not obviously and intentionally numeric.
Why can you not use tabs in YAML?
YAML forbids tab characters for indentation entirely, and a tab used to indent a line is a hard parse error, not a silent surprise. The reason is that a tab has no fixed width, so a parser could not reliably tell how far a tab-indented line is nested relative to a space-indented one. Rather than guess, the specification bans tabs from structural indentation outright. This trips people up constantly because many editors insert tabs by default or on autocomplete, and a tab is visually indistinguishable from spaces:
server:
host: localhost # this line starts with a TAB — parse error
port: 8080 # this line uses spaces
To the eye both lines look indented, but the tab on the first one makes the document invalid. The fix is to configure your editor to insert spaces when you press Tab and to reveal whitespace so you can see the difference. If a YAML file mysteriously fails to parse and everything looks correctly aligned, a stray tab is one of the first things to check. Note that tabs are only banned for indentation; a tab inside a quoted string value is fine, because there it is data rather than structure.
How does indentation change the meaning of a document?
YAML uses indentation to express nesting, so the number of leading spaces on a line determines what a value belongs to, and getting it wrong reshapes the data without any error. Unlike the tab case, an indentation mistake often produces a document that still parses, just into the wrong structure. Compare these two:
parent:
child: value
sibling: other
Here child and sibling are both keys inside parent, because they share the same indentation. Now shift one line:
parent:
child: value
sibling: other # over-indented
This is invalid because sibling is indented more than child but child is a scalar, not a mapping that can contain it. A subtler version under-indents instead, moving a key out of its parent so it becomes a top-level key, and that frequently parses cleanly into a structure you did not intend. The rules to internalise are: siblings must share the exact same indentation, a nested block must be indented more than its parent, and the amount does not matter as long as it is consistent within the block. Two spaces per level is the usual convention. Because these mistakes can pass parsing while corrupting structure, they are the hardest YAML errors to catch by eye.
What other traps catch people out?
Beyond types and indentation, a handful of smaller rules cause repeat failures. The colon that separates a key from its value must be followed by a space: key: value is a mapping, but key:value is a single scalar string, not a key/value pair. Special characters at the start of a scalar, such as a value beginning with @, a backtick, or a brace, need quoting because YAML reserves them. Multi-line strings have their own syntax with the | block scalar preserving newlines and the > folded scalar collapsing them, and mixing those up changes whether your text keeps its line breaks. Comments begin with # and must have a space before them when they follow content on the same line, or they can be swallowed into the value. None of these is complicated, but each one produces a confusing result the first time it bites.
How do you avoid these gotchas in practice?
The single habit that removes most YAML bugs is to quote every scalar whose type is not obviously intended to be a number or boolean, and to indent with spaces only and consistently. That one rule defeats the Norway problem, protects version strings and ZIP codes, and stops accidental null and octal conversions in a single stroke. Configure your editor to insert spaces for tabs and to show whitespace so structural mistakes are visible. Beyond discipline, verifying the parsed result catches the errors that survive: converting your YAML to JSON shows you exactly what a parser sees, because JSON has no type coercion and no ambiguity, so if NO came out as false you will see it immediately. A client-side JSON and YAML converter does this locally in your browser, which matters because configuration files are exactly where database passwords and API keys live, and those should never be pasted into a remote service. Round-trip your YAML to JSON, look at the values that came out, and the coercion surprises stop being surprises.
YAML earns its popularity with readability and comments, but it pays for that friendliness with a grammar that guesses at types and depends on invisible whitespace. Quote anything that should stay text, indent with spaces only and consistently, watch for stray tabs, and verify by converting to JSON. Do those four things and the gotchas in this article stop reaching production.