How-To & Life · Guide · Developer Utilities
How to format YAML
Indentation rules, flow vs block style, anchors and aliases, multi-doc files, and the YAML gotchas (Norway problem, implicit types) that bite CI.
YAML looks simple until it silently misparses. A stray tab, an unquoted yesthat becomes a boolean, a number with a leading zero that becomes octal—YAML has more footguns than JSON and more ways to produce output that looks right but is not. Most of the DevOps world has standardized on YAML anyway, so CI pipelines, Kubernetes manifests, Ansible playbooks, and Docker Compose files all depend on getting the formatting exactly right. Readable, consistent YAML also reduces merge conflicts and makes review diffs mean something. This guide covers indentation rules, when to quote strings, block versus flow style, folded versus literal scalars, key/value alignment, and the difference between a formatter and a linter.
Advertisement
Indentation rules
YAML uses indentation to express structure. Two spaces per level is the universal convention. Tabs are not allowed for indentation—the YAML spec explicitly bans them, and every parser will reject a document indented with tabs. Each nested level must be indented at least one space more than its parent, and all siblings at the same level must share the exact same indentation. The spec does not mandate exactly two spaces, but any consistent number works; the community has settled on two.
server:
host: localhost
ports:
- 8080
- 8443
tls:
enabled: true
cert: /etc/ssl/cert.pemStrings and when to quote them
YAML tries to infer types from unquoted values, and that is where trouble starts.yes, no, true, false, on,off, and their capitalized variants all parse as booleans in YAML 1.1.null, Null, NULL, ~, and an empty value all parse as null. A bare 12345 is an integer. A bare 3.14 is a float. 0777 is octal (YAML 1.1) or a string (YAML 1.2). The safe rule is to quote any string that looks like it could be interpreted as another type—version numbers, country codes, phone numbers, anything that might start with a zero, and any literal yes/no that you want to stay strings.
Single versus double quotes
Single-quoted strings are literal: no escape sequences, and a literal apostrophe inside the string is written as two apostrophes. Double-quoted strings support the full C-style escape set: \n, \t, \uXXXX, and so on. For most config-file strings, single quotes are safer because you do not have to worry about accidental backslash escapes. Use double quotes only when you explicitly need the escape sequences.
message: 'It''s a literal string.' path: "C:\\Users\\me\\file.txt" newline: "line one\nline two"
Block style versus flow style
YAML supports two styles for collections. Block style uses indentation and dashes, which is the readable default for config files. Flow style uses braces and brackets like JSON, which is compact but harder to diff. Flow style is appropriate for short inline collections—a tag list or small record—but unreadable when nested. A common convention is block style for everything except short arrays that fit on one line.
# Block style
services:
web:
image: nginx
ports:
- 80
- 443
# Flow style
services: { web: { image: nginx, ports: [80, 443] } }Folded versus literal scalars
Long strings can be written as block scalars with a | (literal) or> (folded) indicator. Literal preserves every newline exactly. Folded converts single newlines to spaces and paragraph breaks (blank lines) to single newlines, which is useful for wrapping long prose without committing to the wrap points. Both styles accept - to strip the trailing newline, + to keep all trailing newlines, or nothing (clip) to keep one trailing newline.
literal: | line one line two line three folded: > these lines will all be joined with single spaces blank line becomes newline stripped: |- no trailing newline
Anchors, aliases, and merge keys
YAML lets you define reusable values with anchors (&name) and reference them with aliases (*name). The merge key <<: merges an aliased mapping into another. Formatters generally leave these intact because renaming an anchor changes every reference. The merge key is a YAML 1.1 feature and not part of YAML 1.2, so some newer parsers ignore it—check your target runtime before relying on it.
Key/value alignment
Some teams align values vertically for readability: host: localhost,port: 8080. Most formatters do not do this automatically because the alignment breaks the moment a new long key is added and every line has to be realigned. The cleaner convention is a single space after the colon. Reserve vertical alignment for reference tables where the set of keys is stable.
Formatter versus linter
A formatter rewrites a YAML document into a consistent layout: indentation, quoting, block/flow choice, and blank lines. A linter analyzes a document for style or semantic problems without necessarily rewriting: “this key has trailing whitespace”, “this line exceeds 120 characters”, “this value should be a string.” Prettier formats YAML. yamllint lints it with configurable rules. Most serious YAML projects run both, with the formatter on save and the linter in CI.
Multi-document files
A single YAML file can contain multiple documents separated by ---. Kubernetes manifests commonly use this pattern to bundle several resources. Each document is parsed independently, so a syntax error in one does not block the others. Formatters should respect the document separator and format each document on its own. Optionally, a trailing... marks the end of a document explicitly, though it is rarely used.
Common mistakes
Using tabs for indentation. Every YAML parser rejects tabs as indentation. If your file has a tab anywhere at the start of a line, the parser will error, often with a cryptic message about a missing mapping. Configure your editor to use spaces for YAML.
Unquoted Norway. The country code NO parses as booleanfalse in YAML 1.1. Same trap for yes, on,Y. Quote country codes and any other short strings that could be ambiguous.
Leading-zero version strings. version: 007 becomes integer7 (or octal 7) depending on the parser version. Quote version strings.
Inconsistent indentation across siblings. All siblings at the same level must share exact indentation. Two spaces here and three spaces there produces a structure error or, worse, a silently different tree shape.
Trailing whitespace inside strings. Trailing spaces on a line inside a folded block scalar change the folding behavior. A formatter should trim trailing whitespace automatically, but not inside a literal block scalar where the spaces are meaningful.
Forgetting the document separator. Concatenating several YAML documents into one file without --- between them produces one malformed document, not a multi-document stream. Always include the separator.
Mixing block and flow inconsistently. One sublist in block style and the next in flow style makes diffs harder to read. Pick one style per nesting level and stay with it.
Run the numbers
Pretty-print and normalize YAML documents with the YAML formatter. Pair with the JSON formatter when you need to move a config between YAML and JSON formats (YAML 1.2 is a strict superset of JSON), and the diff checker to compare two YAML versions side-by-side before committing a config change.
Advertisement