5 YAML Gotchas Every Developer Hits (Norway Problem, Octal Surprises, and More)

A classic YAML cautionary tale: a config file that stored user country codes silently dropped every Norwegian user from reports. The bug wasn’t in the database or the query — it was one line of config:

country: NO

Under YAML 1.1 semantics, NO is parsed as the boolean false. The country code for Norway was never stored at all.

This is the most famous example of a YAML gotcha, but it’s just one of five traps that catch developers regularly. Here are all five, with examples you can reproduce in seconds.

Test these yourself

Open the YAML Converter →
Paste YAML, see JSON/TOML in real time, and get inline warnings for every gotcha below

1. The Norway Problem (yes/no/on/off → boolean)

YAML 1.1 includes an unusually generous list of boolean literals. Any of these unquoted values become true or false:

Parsed as trueParsed as false
true, True, TRUEfalse, False, FALSE
yes, Yes, YES, yEs, yeS, … (any case)no, No, NO, nO (any case)
on, On, ON, oNoff, Off, OFF, oFf, …

So country: NO silently becomes country: false. The same applies to:

  • Two-letter country codes: NO (Norway)
  • Survey answers: response: Y, answer: N
  • Feature-flag-like strings: logging: off, state: ON

Fix: wrap in quotes.

country: "NO"       # string, correct
logging: "off"      # string, correct
logging: off        # boolean false — probably not what you meant

2. Leading Zero → Octal (01234 ≠ 1234)

YAML 1.1 follows C-style numeric conventions. A number with a leading zero is octal (base 8):

zipcode: 01234        # → 668 (decimal)
zipcode: "01234"      # → "01234" (string)

Places this bites you:

  • Zip codes: American ones often start with 0 (021081096)
  • Product codes / SKUs: SKU-0123 is a string, but 0123 alone becomes 83
  • Bank account numbers: almost always need to be strings
  • Airline flight numbers: 007 doesn’t exist as a flight, but quoting is still standard

Fix: quote anything that starts with 0 and isn’t actually a number.

3. Colons Trigger Base-60 (Sexagesimal) in YAML 1.1

This one feels almost impossible until it happens to you. YAML 1.1 supports base-60 numbers for representing time:

duration: 1:30         # → 90 (1 × 60 + 30)
duration: 3:00:00      # → 10800 (3 × 3600)

Places this bites you:

  • Time values in config: timeout: 1:30 becomes 90
  • Git commit short SHAs: a SHA like 1:2345abc can confuse parsers
  • Version strings: version: 1:2.3 inside a key
  • Port mappings stored raw: mapping: 80:443 becomes one number in some parsers

YAML 1.2 parsers have dropped sexagesimal support, including modern go-yaml (used by Kubernetes) after a 2019 change. But older configs parsed by legacy tools, or YAML 1.1-strict parsers, still hit this. If your toolchain touches both old and new YAML libraries, quote it anyway.

Fix: quote time values.

duration: "1:30"

4. Tabs Are Forbidden in Indentation

Unlike Python, which treats tabs and spaces as interchangeable (sort of), YAML forbids tabs for indentation. The parser either fails loudly or silently misinterprets the structure:

server:
→ host: localhost      # ← tab instead of spaces = parse error
  port: 8080

This is especially painful because:

  • Tab characters are invisible in most editors
  • Copy-pasting from Slack, email, or PDF often converts spaces to tabs
  • Some editors (IntelliJ, older VS Code) insert tabs by default

Fix: configure your editor to insert spaces (2 or 4, consistently). Run a quick check:

grep -Pn '^\t' config.yaml    # lists lines starting with a tab

5. “Numeric-Looking” Strings Get Coerced

YAML is eager to infer types. Anything that looks like a number, date, or boolean gets converted unless you explicitly quote it:

version: 1.0            # → 1.0 (float) — but you wanted the string "1.0"
version: 1.0.0          # → "1.0.0" (string, three dots = not a number)
date: 2026-04-18        # → Date object in many parsers
port: 8080              # → 8080 (integer)
phone: 0123456789       # → parsed as a number (and possibly octal)
sha: 1234567890abcdef   # → "1234..." (string, contains letters)

The trap: version: 1.0 becomes a float, so version == "1.0" comparisons fail, JSON output drops the trailing zero ("version": 1), and your apiVersion check breaks silently.

Fix: quote version strings, date strings, and any identifier that must remain a string.

version: "1.0"
date: "2026-04-18"
phone: "0123456789"

The safest rule of thumb

Quote any value whose semantic meaning depends on it being a string. The cost of one pair of double quotes is zero; the cost of a silent type coercion in production is hours of debugging.

# ✓ Safe
country: "NO"
zipcode: "02108"
duration: "1:30"
version: "1.0"

# ✗ Might explode later
country: NO
zipcode: 02108
duration: 1:30
version: 1.0

Catch these automatically

iTool’s YAML ↔ JSON ↔ TOML Converter flags all four dangerous patterns (Norway, octal, sexagesimal, tab indent) inline as you type, plus detects Kubernetes / Docker Compose / GitHub Actions schemas automatically.

Frequently Asked Questions

Why does YAML turn the country code NO into false?

YAML 1.1 treats unquoted yes/no/on/off (any case) as boolean values. NO is parsed as false. Always quote country codes and two-letter identifiers.

How do I write a zip code starting with 0 in YAML?

Wrap it in quotes: zipcode: "01234". Without quotes, YAML 1.1 parses it as octal and converts it to 668. This also affects product codes and bank account numbers.

Can I use tabs for YAML indentation?

No. The YAML spec forbids tabs for indentation. Use 2 or 4 spaces consistently. If your editor auto-inserts tabs, change the setting to 'insert spaces'.

Does YAML 1.2 fix the Norway problem?

Partially. YAML 1.2 narrows true boolean values to just true/false (lowercase), but many parsers — including the one Kubernetes uses — still default to YAML 1.1 semantics. Quoting is the only truly portable solution.

Is there a tool to catch these pitfalls automatically?

Yes. iTool's YAML ↔ JSON ↔ TOML converter detects all five gotchas (Norway problem, octal, sexagesimal, tab indentation, ambiguous strings) and warns you inline as you type.