json:yaml

YAML indentation rules

Whitespace is syntax in YAML. These are the rules, why tabs fail, and the list alignment mistake almost everyone makes at least once.

The rules

  1. Spaces only. Tab characters are forbidden in indentation. This is not a style preference — the specification prohibits it and every parser rejects it.
  2. Two spaces per level is the near-universal convention. Four is legal. One is legal and unreadable. What matters is that it is consistent within a file.
  3. Siblings share a column. Every key in the same mapping must start at exactly the same column. Off by one is a different mapping or an error.
  4. Children indent further than their parent. Any amount further, as long as it is consistent among the siblings.
  5. The hyphen counts as indentation for anything on the same line as it, which is why nested keys under a list item line up with the first character after the hyphen and the space.

Why tabs fail, and how to stop it

A file indented with tabs looks perfectly aligned in your editor and fails to parse with a message about a tab character not being allowed. The reason the spec forbids them is that tab width is a display setting, so a tab-indented document would nest differently depending on who opened it.

Fix it once, in your editor config:

# .editorconfig
[*.{yml,yaml}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

To find existing tabs: grep -Pn '\t' config.yaml. To fix the whole file at once, paste it into the YAML formatter, which re-emits it with consistent spaces.

Where list items go

Both of these are valid and mean exactly the same thing:

Indented (recommended)
ports:
  - 8080
  - 9090
Flush with the key
ports:
- 8080
- 9090

The indented form is what Kubernetes, Ansible, and GitHub Actions documentation uses, and it makes the parent-child relationship visible at a glance. Pick it, and be consistent — mixing both in one file is legal and confusing.

Objects inside a list

The keys of a list item align with the first key, which sits one space after the hyphen:

containers:
  - name: api          # 'name' starts at column 5
    image: api:2.4.1   # 'image' must start at column 5 too
    ports:
      - containerPort: 8080

Putting image at column 7 to line it up under name's value is the single most common YAML mistake. It produces a bad-indentation error.

Depth as a warning sign

Past about five levels, indentation stops helping. The content is pushed so far right that a reviewer cannot see which branch a line belongs to, and adding a level means re-indenting everything below it.

Deep files are also where the YAML validator earns its keep: reading the parsed output is far quicker than counting spaces by eye.

When a file gets that deep, the structure is usually the problem rather than the format. Split it into multiple files, flatten a level with dotted keys, or use anchors to lift repeated blocks to the top.

Questions people ask

Can I use tabs in YAML?
Not for indentation. The specification forbids it and every parser rejects it, because tab width is a display setting and the nesting would differ per reader. Tabs inside a quoted string are fine.
How many spaces should I use?
Two. It is the convention across Kubernetes, Ansible, Docker Compose, and GitHub Actions. Four is valid. What matters most is consistency within a file.
Should list items be indented under their key?
Both forms are valid and identical in meaning. Indenting them is what ecosystem documentation does and makes the relationship visible, so prefer it.
Why does my nested key throw a bad indentation error?
Inside a list item, the keys align with the first key — one space after the hyphen. Aligning a second key under the first key's value instead is the most common cause.
How do I find tabs in a file?
grep -Pn '\t' config.yaml will show the line numbers. Preventing it is better: set indent_style = space for yaml files in .editorconfig.