Skip to content
datahacks.dev
YAML

A Cheat Sheet of YAML Syntax for Everyday Config Files

One page of YAML syntax: scalars, quoting, collections, block strings, anchors, documents, comments and the values that change type. Copy-ready snippets.

6 min read
Summarize in AI
Flat illustration of a tree of nested objects beside the document it came from, with the YAML logo.

A reference to keep open while you edit. Each section has the syntax, a one-line rule and the trap that goes with it. The details and the evidence are in the posts linked at the end, and every claim here was checked against a real parser in this cluster.

Scalars

YAML
string: hello world
number: 42
float: 3.14
boolean: true
nothing: null      # also ~ or an empty value
date: 2026-10-27

A plain scalar is whatever the parser resolves it to. Strings need no quotes unless they would resolve to something else or contain syntax characters.

Quoting

YAML
single: 'it''s literal, no escapes: \n stays \n'
double: "tab\there, newline\n, unicode é"
country: "NO"          # quoted so it is not False
version: "3.10"        # quoted so it is not 3.1
zip: "01234"           # quoted so the zero stays
colon: "a: b"          # quoted because of ': '
hash: "red #fff"       # quoted because of ' #'

Rule: **quote anything that is a code, a version, an identifier or has : or #.** Trap: an unquoted yes, no, on, off is a boolean in YAML 1.1 parsers.

Mappings

YAML
person:
  name: Ana
  age: 31
inline: {name: Ana, age: 31}

Keys at the same indentation are siblings. Keys must be unique, and PyYAML keeps the last of a duplicate without warning.

Sequences

YAML
fruits:
  - apple
  - pear
inline: [apple, pear]
records:
  - name: a
    v: 1
  - name: b
    v: 2

In a list of mappings, the keys after the first line up with the first key, two columns after the dash.

Empty values

YAML
empty_list: []
empty_map: {}
null_value:        # null, not an empty list
empty_string: ""

Block strings

YAML
literal: |
  line one
  line two
folded: >
  these lines are
  joined with spaces
strip: |-
  no final newline
keep: |+
  keeps trailing blank lines

| keeps newlines, > folds them into spaces, - strips the last newline, + keeps all trailing blank lines, and the default keeps exactly one. Indentation inside the block is content.

Comments

YAML
# a full-line comment
key: value  # a trailing comment, needs a space before the hash

No block comments. A hash inside a block string is text, not a comment. Most parsers discard comments, so a program that rewrites the file may delete them; use a round-trip library for that.

Anchors, aliases and merge

YAML
defaults: &defaults
  retries: 3
  timeout: 30
service_a:
  <<: *defaults
  timeout: 60
service_b: *defaults

&name defines, *name reuses, << merges a mapping's entries into another with local keys winning. The merge is shallow, and aliases share one object when loaded.

Documents and directives

YAML
%YAML 1.2
---
first: document
...
---
second: document

Three dashes start a document, three dots end one, and a stream can hold many. safe_load accepts one document, and safe_load_all reads all of them.

Tags and types

YAML
explicit_string: !!str 123
explicit_int: !!int "42"
binary: !!binary aGVsbG8=

An explicit tag overrides type guessing. Avoid language-specific tags (!!python/object): they can execute code in unsafe loaders.

Values that change type when unquoted (YAML 1.1 parsers)

WrittenLoads as
yes, on, trueboolean true
no, off, false, NOboolean false
010integer 8
0x1Finteger 31
12:30integer 750
22:22integer 1342
3.10float 3.1
2026-01-05a date
~, nullnull

YAML 1.2 parsers keep most of the above as strings or decimal numbers.

Quick checks

Shell
python3 -c "import yaml,sys,json; print(json.dumps(yaml.safe_load(open(sys.argv[1])), indent=1, default=str))" file.yaml
yamllint file.yaml
yq '.' file.yaml

The first prints the parsed structure, the second lints style and syntax, the third parses and re-emits the file.

How to use the sheet

Keep it for the moments that cost people time. Before you add a value, look at the quoting section: if the value is a code, a version or an identifier, quote it, whatever it looks like today. Before you nest something, look at the lists-of-mappings example and count columns. Before you paste a block, check the indentation of the destination, and the style of the file you are pasting into. And before you commit, run the three commands at the bottom, because a parse you ran is worth more than a file you read.

The sheet leaves out what is rarely needed on purpose. Complex keys, with the question mark syntax, ordered mappings and sets, custom tags and the full list of escape sequences exist in the specification and appear in almost no real configuration. If you meet them, read the relevant chapter of the specification, and consider whether the file would be clearer without them. Simpler YAML is more portable between parsers, and portability is what protects a file from the differences between versions.

Mistakes the sheet is built to prevent

Most YAML problems in practice come from a short list. A tab in the indentation, which the parser rejects with a message about a token it cannot start. A colon in an unquoted value, which the parser takes as another key. A value that looks like something else, such as NO, 010 or 22:22, which is silently converted. A list whose items were commented out, which becomes null instead of an empty list. A duplicate key after a merge, which is silently overwritten. A block string with trailing spaces or a missing chomping indicator, which carries an invisible newline into a comparison. And an anchor whose merge looked deep and was shallow.

Each has an example above and a fix: spaces only, quotes around anything with a colon-space, quotes around codes, explicit empty collections, a linter that reports duplicates, a strip indicator on values you compare, and code that does the deep merge. If you remember only the short list and the three commands, you avoid most of the incidents that the longer posts describe.

Reading an error quickly

Parse errors name a line and a column, and the text depends on the parser. Three messages cover most cases. "Found character that cannot start any token" means a character is in a place where none may start a value, usually a tab or an at sign. "Mapping values are not allowed here" means a colon appeared where the parser was still inside a value, usually from an unquoted colon or a line that is indented one space too far. "Did not find expected key" means a line is indented to a level that does not match any open mapping. The error names where the parser gave up, which is often the line after the mistake, so look at the lines above it too.

Where to read more

The cluster hub is YAML syntax you need to stop guessing at. Each section has a post: indentation, quoting, multiline strings, lists and mappings, anchors and the two language versions. The official reference is the YAML 1.2.2 specification, and the YAML 1.1 specification for the older rules. Try snippets in the YAML formatter and the YAML to JSON tool.

When a cheat sheet is not enough

You are debugging a failure. A parse error needs the error catalog, not the syntax card (fixing YAML errors that make no sense).

The file is read by a particular tool. Compose, CI systems and Kubernetes define their own schemas on top of YAML. Their reference decides what is valid.

You need to be sure of types. Syntax is the first half. A schema or a typed model checks the values.

You are writing YAML from code. Use a library, and read its documentation about quoting and style.

Also inTooling
Share

Keep reading

Get new articles by email

We send one email when a new article is published. No spam.

Unsubscribe in one click. No spam, ever.