YAML 1.2 Tabs vs Spaces: Indentation Rules, Parse Errors & Fixes
YAML is everywhere — Kubernetes manifests, GitHub Actions, Docker Compose, Ansible playbooks, Next.js config. It looks simple until a misplaced space silently breaks your deployment at 3 AM. This guide covers the errors developers hit most often and how to fix them.
Why YAML Indentation Is So Painful
YAML uses indentation to represent structure — like Python, but stricter. There are no closing brackets to catch misalignment, no linting built into most text editors by default, and error messages from YAML parsers range from cryptic to misleading.
The fundamental rules are simple, but the edge cases are many:
- Only spaces are allowed — tabs cause an immediate parse error
- The number of spaces per indentation level can vary, but must be consistent within a block
- All keys at the same level must be indented by the same amount
- Child elements must be indented more than their parent
Does YAML 1.2 Allow Tabs for Indentation?
No — tabs are explicitly forbidden in both YAML 1.1 and YAML 1.2. This is a hard rule with no exceptions. A single tab character in your indentation triggers an immediate parse error:
found character '\t' that cannot start any tokenWhy no tabs? Different editors render tabs as different widths (2, 4, or 8 spaces depending on settings). Since YAML uses indentation to define structure, tab width ambiguity would cause the same file to parse differently across editors. The spec bans tabs entirely to guarantee consistent parsing regardless of environment.
YAML 1.2 vs YAML 1.1: Both versions forbid tabs for indentation. YAML 1.2 (released 2009) is stricter than 1.1 in some areas — it removed the yes/no/on/off boolean coercions — but the tab prohibition is identical in both versions. If you're looking for whether YAML 1.2 allows tabs: it does not.
Configure your editor to insert spaces on Tab for YAML files via .editorconfig:
[*.yml]
indent_style = space
indent_size = 2
[*.yaml]
indent_style = space
indent_size = 2The 5 Most Common YAML Errors
1. Tabs Mixed With Spaces
The most common source of YAML parse errors. Tabs are visually indistinguishable from spaces in most editors but cause an immediate found character '\t' that cannot start any token error.
# WRONG — tab before port:
server:
port: 8080 # ← This tab will break everything
# CORRECT — spaces only
server:
port: 8080Fix: Set your editor to insert spaces on Tab for YAML files. In VS Code: Format On Save + the YAML extension. In .editorconfig:
[*.yml]
indent_style = space
indent_size = 22. Inconsistent Indentation Within a Block
All keys in a mapping must start at the same column. Mixing 2-space and 4-space indentation within the same block causes a bad indentation of a mapping entry error.
# WRONG
database:
host: localhost
port: 5432 # ← 4 spaces instead of 2
# CORRECT
database:
host: localhost
port: 54323. Missing Space After the Colon
In YAML, a colon must be followed by a space (or newline) to be treated as a key-value separator. Without the space, the entire key:value is treated as a string.
# WRONG — treated as a single string "host:localhost"
database:
host:localhost
# CORRECT
database:
host: localhost4. Unquoted Special Values
YAML auto-infers types from unquoted scalars. This causes silent data corruption where the YAML is technically valid but the parsed value is wrong.
# YAML 1.1 type coercion surprises:
enabled: yes # → boolean true (not string "yes")
country: NO # → boolean false (Norway problem!)
version: 1.10 # → float 1.1 (trailing zero lost)
port: 08080 # → integer 4160 (octal in some parsers!)
date: 2024-01-15 # → Date object (not string)
# Safe versions (quoted):
enabled: "yes"
country: "NO"
version: "1.10"
port: "08080"
date: "2024-01-15"5. Wrong Sequence Indentation
List items (sequences) use a dash (-) and must be indented consistently. A common mistake is forgetting that the dash is part of the indentation.
# WRONG — services not indented under app
app:
name: my-app
services:
- api
- web
# CORRECT
app:
name: my-app
services:
- api
- webReading YAML Error Messages
When a YAML parser fails, the error message contains three key pieces of information:
- reason — the human-readable error type (e.g.,
bad indentation of a mapping entry) - line — the line number where the error was detected (1-indexed)
- column — the column where the parser got confused
Important: the reported line is where the parser noticed the problem, not necessarily where the mistake is. An indentation error on line 5 might be caused by a missing space on line 3. Always look at the lines before the reported error too.
Multi-line Strings: | vs >
Two block scalar indicators handle multi-line strings:
# Literal block (|) — preserves newlines
script: |
#!/bin/bash
echo "Hello"
echo "World"
# Result: "#!/bin/bash
echo "Hello"
echo "World"
"
# Folded block (>) — wraps to single line
description: >
This is a long description
that spans multiple lines
for readability.
# Result: "This is a long description that spans multiple lines for readability.
"Use | for shell scripts, code, and content where newlines matter. Use > for long prose strings where you want line wrapping in the YAML source but a single paragraph in the output.
Anchors and Aliases: DRY YAML
YAML has a built-in mechanism for reusing values: anchors (&name) and aliases (*name). This is especially useful in CI/CD configuration files.
# Define a reusable block
defaults: &defaults
environment: production
replicas: 3
timeout: 30
# Reuse it with merge key <<
api-service:
<<: *defaults
port: 8080
worker-service:
<<: *defaults
port: 8081Note: anchors and aliases are resolved during parsing. When you convert YAML to JSON, aliases are expanded — the deduplication is lost in the JSON output.
YAML Indentation: 2 Spaces or 4 Spaces?
The YAML specification does not mandate a specific number of spaces — 2, 4, or any consistent amount works. The only hard rules are:
- Use the same number of spaces consistently within each block
- Child elements must have more indentation than their parent
- Tabs are never allowed — spaces only
In practice, 2 spaces is the de facto standard in most ecosystems: Kubernetes manifests, GitHub Actions, Docker Compose, and Ansible all use 2 spaces by convention. Most YAML linters default to 2. Use 2 unless your project enforces 4.
# 2 spaces — most common
server:
host: localhost
port: 8080
database:
url: postgres://localhost/mydb
pool: 10
# 4 spaces — also valid, less common
server:
host: localhost
port: 8080
database:
url: postgres://localhost/mydb
pool: 10
# WRONG — mixing 2 and 4 within the same block
server:
host: localhost
port: 8080 # ← parser error: inconsistent indentationSet your editor to enforce 2-space YAML indentation globally via .editorconfig:
[*.{yml,yaml}]
indent_style = space
indent_size = 2YAML Sequence (List) Indentation Explained
Sequences (lists) are the most common source of indentation confusion. The dash - that marks each list item is part of the indentation, not a separate character.
# Pattern 1 — dash at same level as parent key (compact, common in K8s)
services:
- api
- web
- worker
# Pattern 2 — dash indented 2 spaces from parent (more readable)
services:
- api
- web
- worker
# Both are valid — but DON'T MIX within the same list:
services:
- api
- web # ← parse error: inconsistent dash position
# Nested list — each level adds indentation
app:
name: my-app
services:
- name: api
port: 8080
env:
- NODE_ENV=production
- PORT=8080
- name: worker
port: 8081The rule for nested objects inside a list: the keys of the object must be indented relative to the dash. The dash itself counts as 2 characters (dash + space), so the object keys start at the same column or further right:
# CORRECT — keys aligned after the dash+space
users:
- name: Alice # dash at col 2, name at col 4
role: admin # role also at col 4
- name: Bob
role: viewer
# WRONG — keys not aligned with the first key
users:
- name: Alice
role: admin # ← 'bad indentation of a mapping entry'
# role should be at col 4, not col 2Quick Debugging Checklist
- Run your YAML through a validator (like the one below) to get the exact line/column
- Check for tabs — search-and-replace all tabs with spaces
- Verify indentation consistency — all keys at the same level should align
- Quote any value that looks like a boolean, number, date, or null (
yes/no/true/false/null/~) - If error points to line N, inspect lines N-3 to N as well
- Use a YAML-aware editor with syntax highlighting to make structure visible
Use the YAML Validator to paste your config and get instant error feedback with line/column context. For converting between YAML and JSON, use YAML to JSON.
Frequently Asked Questions
Can I use tabs for YAML indentation?▾
No. The YAML specification explicitly forbids tab characters for indentation. Only spaces are allowed. This is a hard rule with no exceptions — a tab character will cause a parse error. Configure your editor to insert spaces when you press Tab (most editors have a 'Tabs → Spaces' setting per language or project). The .editorconfig file is a portable way to enforce this across editors.
Should I use 2 or 4 spaces for YAML indentation?▾
The YAML spec doesn't mandate a specific number — both 2 and 4 spaces are valid as long as you're consistent within each block. In practice, 2 spaces is the community standard: Kubernetes, GitHub Actions, Docker Compose, and Ansible all use 2 spaces. Most editors and linters default to 2. Use 2 spaces unless your team or project enforces 4. The only thing that matters is consistency — never mix 2 and 4 within the same file.
What are the YAML indentation rules?▾
Three core rules: (1) Only spaces are allowed — tabs are forbidden by the spec and cause an immediate parse error. (2) All keys in the same mapping (object) must be indented by the same amount. (3) Child elements must have more indentation than their parent. Beyond these, YAML is flexible: you can use 2 spaces, 4 spaces, or any consistent amount per level. The most common style is 2 spaces per level.
What does 'bad indentation of a sequence entry' mean in YAML?▾
This error means a list item (marked with '-') is not aligned at the same column as the other items in the same list, or it is indented incorrectly relative to its parent key. The most common cause: the '-' dash is at the wrong column — usually it should be indented 2 spaces from the parent key, and all dashes in the same list must be at the exact same column. Example: if 'services:' is at column 0, the list items should have their '-' at column 2. Always look at the lines before the reported error too — the indentation mistake is often one or two lines above where the parser complains.
How do I check YAML syntax online?▾
Paste your YAML into the YAML Validator at devessentials.dev/yaml-validator — it reports the exact line and column of every syntax error, including tab characters, bad indentation, and sequence misalignment. For local validation, run: python3 -c "import yaml,sys; yaml.safe_load(sys.stdin)" < file.yml or npx js-yaml file.yml. Most editors also support real-time YAML linting with the appropriate extension (YAML extension in VS Code).
Why does YAML parse 'no' and 'yes' as booleans?▾
YAML 1.1 (still used by many parsers) defines yes, no, on, off, true, false as booleans — case-insensitive. The infamous 'Norway problem': the ISO country code 'NO' becomes boolean false in a YAML mapping. Fix: always quote these values when you intend them as strings: 'no', 'yes', 'on', 'off'. YAML 1.2 dropped the yes/no/on/off booleans, but library support varies — js-yaml's default is YAML 1.1.
How do I write a multi-line string in YAML?▾
Two block scalar styles: literal block (|) preserves newlines exactly — each line in the YAML becomes a line in the string. Folded block (>) converts single newlines to spaces, treating the block as a wrapped paragraph (double newlines become single newlines). Both styles strip leading indentation relative to the first content line. Example: description: | → 'This is line 1\nThis is line 2'. Use | for shell scripts or code, > for long prose descriptions.