Edge cases: complex keys, indentation, gotchas

YAML · Expert · 12 min

These details explain the odd parse results and errors that remain once you know the basics.

A few corners of the spec that come up in practice:

  • Keys needn't be strings. 1: one has an integer key, true: x a boolean one (in YAML 1.1, on: becomes True, famously breaking GitHub Actions' on: key in PyYAML-based tools). JSON conversion then stringifies or fails.
  • Complex keys: ? introduces an explicit key, which can be a sequence or mapping. Python can't use a list as a dict key, so loaders may reject such documents.
  • Implicit keys (without ?) must fit on one line and are limited to 1024 characters.
  • Plain multi-line scalars are allowed: a plain value may continue on more-indented lines, and the line breaks fold into spaces. This hides mistakes such as a forgotten - that turns two list items into one string.
  • Indentation of sequences in mappings: key: followed by - item at the same column is valid, because the - counts as indentation. But within one sequence all dashes must align.
  • Tabs are forbidden for indentation but allowed as separation inside lines and inside quoted strings.
  • Byte order marks are allowed only at the start of the stream; encodings must be UTF-8, UTF-16 or UTF-32.
  • Document markers in strings: a line starting with --- or ... at column 0 inside a block scalar ends the document; indent it.
  • Duplicate keys are invalid by the spec even though many parsers accept them.

Example

1: one                 # integer key
on: push               # YAML 1.1 parsers: key is the boolean True
? [lat, lon]           # complex key: a sequence
: point
items:
- first
- second
  third                # not a new item: continues "second" -> 'second third'
message: |
  a line
  --- indented, so it is text, not a document marker

# PyYAML (YAML 1.1) loads the first two keys as 1 and True, and
# fails on the complex key: "found unhashable key"

Remember

  • Keys can be numbers, booleans or even collections
  • Plain scalars can continue on indented lines, hiding missing dashes
  • Lines starting with --- or ... at column 0 end a document, even in a block scalar

Watch out for

  • Dropping the - on a list item so it silently becomes part of the previous item's string.

Check yourself

  1. In the YAML below, how many items does the list have? - a - b c

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: yaml.org/spec/1.2.2/#chapter-6-structural-productions