YAML pitfalls: the Norway problem, indentation, and anchors
YAML looks like the friendly config format until it silently converts 'NO' to false. Here are the traps in YAML 1.1, why 1.2 fixes some of them, and when to switch to JSON.
The Norway problem
The most famous YAML footgun:
countries:
- GB
- IE
- NO
- FR
Parsed with a YAML 1.1 parser, NO becomes the boolean false. Norway silently vanishes.
YAML 1.1 has a long list of "boolean-ish" strings that get auto-converted unless quoted: yes, no, y, n, Y, N, true, false, on, off, plus every case variation. Country codes, chemical symbols, initials, and airport codes get eaten regularly.
YAML 1.2 (2009) fixed this - only true and false are booleans. But most parsers still default to 1.1 for compatibility, including PyYAML's default load. Check your parser's version.
The safe habit: always quote strings that could be misinterpreted. "NO" is a string; NO is a coin flip.
Indentation is the syntax
Unlike JSON's braces and brackets, YAML uses indentation to define structure. Get it wrong and you get either a parse error or, worse, a silently different structure. Two rules save most people:
- Never use tabs. The YAML spec forbids them at the start of a line. Some parsers accept them, most don't. Configure your editor to insert spaces.
- Pick one indent width and stick to it. 2 or 4 spaces, applied consistently. Mixed indent breaks parsers.
The failure mode that costs the most time: mis-indenting a child key so it becomes a sibling.
service:
name: web
port: 8080 # port is now a child of name, not service. syntax error.
Anchors and aliases
YAML supports references - define once, use many times:
defaults: &defaults
timeout: 30
retries: 3
production:
<<: *defaults
host: prod.example.com
staging:
<<: *defaults
host: staging.example.com
Great in principle, three problems in practice:
1. JSON has no equivalent. Converting YAML โ JSON expands every anchor, exploding file size. If you're going through JSON at any point in your pipeline, anchors buy you nothing at rest.
2. Merge keys (<<) are a YAML 1.1 extension. Not in 1.2 core. Most parsers still support them, but not all.
3. Billion laughs attack. Recursive anchors expand exponentially. A malicious 200-byte YAML can produce gigabytes of parsed data. safeLoad mitigates in some parsers; unbounded expansion is a real DoS vector for services that accept YAML from users.
Multi-line strings: three formats, subtle differences
folded: >
This becomes a single line
with spaces between the words.
literal: |
This preserves
every line break.
double-quoted: "This handles \n escape sequences and \"quotes\"."
Add - to strip trailing newlines (>-, |-), + to keep them all (>+, |+). Bare > and | "clip" - keep one trailing newline. This is the source of unexpected extra newlines in generated YAML.
Numbers that aren't numbers
YAML 1.1 parses 012 as octal (10 in decimal). YAML 1.2 requires 0o12 for octal - bare 012 is a string. If you have Docker port mappings like 010, quote them.
Also: 1.2e3 is a float, 1.2.3 is a string. Version numbers must be quoted.
When to switch to JSON
YAML's advantages over JSON are:
- Comments
- Multi-line strings
- Anchors / merge keys
- Less punctuation
If you're not using any of those, JSON is safer - no boolean coercion, no indentation traps, no version differences.
The common middle ground: write YAML, ship JSON. Author config in YAML for readability, convert once at build time, ship the JSON. All the ergonomics; none of the runtime traps.
YAML โ JSON does the conversion locally in your browser, both directions, using js-yaml in YAML 1.2 mode. Nothing is uploaded - safe for config files that contain secrets.
The comparison workflow
When YAML behaves unexpectedly, the fastest debugging trick is: convert to JSON and eyeball it. The structure that actually parsed is often not the structure you thought you wrote. If two YAML files should be equivalent but aren't producing the same behavior, convert both to JSON and diff them structurally.
JSON Diff does that structural comparison - key order doesn't matter, so you see real semantic differences rather than incidental formatting noise.
Related tools:
- JSON Formatter - to pretty-print the converted output.
- JSON Diff - to compare two configs that should behave the same.
Tools mentioned in this post
Related reading
TOML vs YAML vs JSON: picking a config format in 2026
Rust picked TOML. Python packaging picked TOML. Cloudflare Workers picked TOML. Here's why the config landscape shifted, and how to move between TOML, YAML, and JSON without breakage.
.env files in 2026: parsing, secrets management, and portability
Every framework reads .env slightly differently. Here's the shared subset that works everywhere, the security pitfalls, and how to sync .env with JSON, YAML, and cloud secret stores.
JSON to TypeScript: workflows that scale beyond a single sample
A one-shot JSON โ interface tool is great for demos and dead for production. Here are the patterns real teams use to keep types in sync with real APIs.
The best free physics editor alternatives for 2D game devs in 2026
Every 2D game needs collision shapes, and every paid physics editor charges you for them. Here's what a physics body editor actually does, what to look for in a free one, and how the current free options - desktop and browser - stack up in 2026.
Shan builds 712 Tools. He holds a Master's degree in Mechanical Engineering and now works as a Software Engineer, shipping browser-based developer utilities out of Ontario, Canada. Learn more ยท 712studiogames@gmail.com