YAML Gotchas

The Norway Problem & Type-Coercion Traps

YAML tries to guess the type of every unquoted value. Usually that is convenient — but a handful of values change meaning in ways that surprise developers, and different parsers disagree. Here are some traps worth knowing, with fixes and live examples.

01 — The Norway Problem

yes / no / on / off become booleans

Under YAML 1.1 (PyYAML and many CI tools), no is the boolean false. So a country list that includes Norway, abbreviated NO, silently becomes false.

Problem

country: NO

Fix — quote the value

country: "NO"

GitHub Actions on: trigger

The same trap bites GitHub Actions: the on: trigger key is the YAML 1.1 boolean true, so some tools see true: instead of on:. GitHub Actions itself handles it, but third-party parsers and linters may not.

Try it in the validator →
02 — Octal Numbers

Leading zeros become octal (ZIP codes, versions)

A value like a ZIP code with a leading zero can be parsed as an octal number — or lose the leading zero entirely, turning 01234 into 668 (octal) or 1234 (truncated).

Problem

zip: 01234

Fix — quote it

zip: "01234"
Try it in the validator →
03 — Sexagesimal

Time-like values become base-60 numbers

YAML 1.1 reads 22:30 as a sexagesimal (base-60) number — 22 × 60 + 30 = 1350 — not a time string. Port numbers, durations, and cron expressions written as HH:MM are all at risk.

Problem

start: 22:30

Fix — quote it

start: "22:30"
Try it in the validator →
04 — Version Numbers

Version strings lose trailing zeros

Write a version as a bare number and YAML treats it as a float: 1.20 becomes 1.2. The trailing zero is silently dropped — a version string that was semantically different is now equal.

Problem

version: 1.20

Fix — quote it

version: "1.20"
Try it in the validator →
05 — How to Avoid

Preventing type-coercion bugs

Quote any value that should stay a string

Especially yes/no/on/off, leading-zero values, time-like strings (HH:MM), and version strings with trailing zeros.

Prefer YAML 1.2-compliant parsers

YAML 1.2 drops the boolean aliases (yes/no/on/off) and the sexagesimal notation entirely. The eemeli yaml package used here follows YAML 1.2 by default.

Use safe loaders

In Python, use yaml.safe_load() instead of yaml.load(). The safe loader still coerces types under YAML 1.1, so quoting remains the safest defence.

Validate before you ship

This tool runs 100% in your browser — your YAML is never uploaded or executed. It warns on all four of the above patterns and deep-links to this article for each one.

Open the YAML validator →