YAML 02 ๐ Syntax Fundamentals and Significant Indentation Rules
YAML’s syntax is deceptively simple. There are no braces, no closing tags, no semicolons. Structure is expressed entirely through indentation and line breaks, which means the whitespace you cannot see is the syntax the parser reads. This chapter covers the foundational rules that govern every YAML file: the indentation requirement, the prohibition on tabs, the colon-space separator for key-value pairs, and the scalar styles that determine how strings are read and stored.
The sections that follow walk through block structure and indentation depth, the tab prohibition and why it exists, the key-value syntax and the colon trap, and the block scalar indicators that preserve or fold line breaks. Each rule is paired with the failure it prevents, because YAML errors are almost always whitespace errors that the eye cannot detect.
Key point: YAML structure is determined by spaces only, never tabs, and every item at the same nesting level must use identical indentation; a single misplaced space changes the meaning or breaks the parse.
Why indentation rules exist
The significant whitespace problem. YAML borrows Python’s approach to structure: indentation defines nesting. A key indented under another key is its child; a key at the same indentation is its sibling. The specification states that “in YAML block styles, structure is determined by indentation” and that “indentation is defined as a zero or more space characters at the start of a line” . The amount of indentation is a presentation detailโtwo spaces, four spaces, or any consistent number will workโbut the relative indentation is the structure itself.
The tab prohibition problem. The specification is explicit: “tab characters must not be used in indentation, since different systems treat tabs differently” . Tabs are permitted inside quoted strings and comments, but never at the start of a line to indicate nesting . The reason is portability: a tab is not a fixed number of spaces, so a file indented with tabs may parse correctly on one editor and break on another. Most modern editors can be configured to insert spaces when the tab key is pressed, which is the recommended setup for YAML work.
The invisible error problem. YAML’s whitespace sensitivity means errors are often invisible. A line that looks correctly indented to the eye may contain a tab where a space was expected, or one extra space that shifts a key into the wrong parent. The error message is typically crypticโ”mapping values are not allowed in this context” is the most commonโand points to a line that appears fine . The discipline is mechanical: check for tabs first, then check sibling alignment, then check for unquoted colons.
a. Block structure and indentation depth
YAML has two structural styles: block and flow. Block style uses indentation and newlines to express structure; flow style uses braces and brackets, similar to JSON. Most configuration files use block style, and the rules below apply to it.
The amount of indentation per level is a convention, not a requirement. The specification does not mandate two spaces or four spaces; it requires only that sibling items share the same indentation and that children are indented more than their parent . Two spaces is the most common convention in infrastructure tooling, and some projects recommend it for consistency .
# Two-space indentation (common convention)
server:
host: localhost
port: 8080
# Four-space indentation (also valid)
server:
host: localhost
port: 8080
The rule that breaks most files is inconsistent indentation between siblings. If one key in a mapping is indented two spaces and the next is indented three, the parser reads the second as a child of the first, which is usually a type error because a scalar value cannot have children .
# INVALID: ports is indented one space more than image
services:
app:
image: myapp
ports:
- "3000:3000"
# The parser sees "ports" as a child of the "image" scalar value
b. Key-value syntax and the colon trap
A mapping entry is written as key: value. The colon must be followed by a space or a newline. A colon without a following space is part of the key or the value, not a separator.
This rule causes the most common “mapping values are not allowed” error when a value contains a colon followed by a space but is not quoted. A URL like postgres://user:pass@host:5432/db contains :pass and :5432; the parser reads the first colon as a key separator and then finds another colon where a mapping cannot begin .
# INVALID: unquoted URL with colons
database:
url: postgres://user:pass@host:5432/db
# VALID: quoted value
database:
url: "postgres://user:pass@host:5432/db"
The same applies to unquoted times like 10:30 and Windows paths like C:\Users. The habit that prevents all of these is to quote any value containing a colon, or at minimum any colon followed by a space.
c. Block scalar indicators: | and >
Multi-line strings use block scalar indicators. The pipe | preserves newlines and indentation; the fold > replaces single newlines with spaces, joining lines into a paragraph . The indentation of the content under the indicator determines what is included in the string.
# Literal block: newlines preserved
message: |
Line one.
Line two.
Line three.
# Folded block: newlines become spaces
description: >
This is a long sentence
that will be joined into
a single line.
The indentation under | or > must be consistent, and it becomes part of the string’s content for the literal style . If the first line of the content begins with a space, or if the content is empty on the first line, an explicit indentation indicator is required to prevent the parser from inferring the wrong level.
# Explicit indicator: content starts at column 2 relative to the key
source: |2
indented content
Complete Example Session
# ============================================
# PART 1: BLOCK MAPPING WITH CONSISTENT INDENTATION
# ============================================
application:
name: my-service
version: 1.0.0
replicas: 3
# ============================================
# PART 2: NESTED MAPPING (TWO SPACES DEEPER)
# ============================================
database:
host: db.example.com
port: 5432
credentials:
username: app_user
password: "secret"
# ============================================
# PART 3: BLOCK SEQUENCE
# ============================================
environments:
- development
- staging
- production
# ============================================
# PART 4: THE COLON TRAP (QUOTED URL)
# ============================================
connection:
url: "postgres://user:pass@host:5432/db"
# ============================================
# PART 5: LITERAL BLOCK SCALAR
# ============================================
script: |
#!/bin/bash
echo "Hello"
echo "World"
# ============================================
# PART 6: FOLDED BLOCK SCALAR
# ============================================
description: >
This service handles user authentication
and session management for the entire
platform.
# ============================================
# PART 7: THE PARSED MENTAL MODEL
# ============================================
# application: { name: "my-service", version: "1.0.0", replicas: 3 }
# database: { host: "db.example.com", port: 5432,
# credentials: { username: "app_user", password: "secret" } }
# environments: ["development", "staging", "production"]
# connection: { url: "postgres://user:pass@host:5432/db" }
# script: "#!/bin/bash\necho \"Hello\"\necho \"World\"\n"
# description: "This service handles user authentication and session
# management for the entire platform.\n"
The parts covered block mapping, nested mapping with two-space depth, block sequences, the quoted-colon pattern, literal and folded block scalars, and the parsed data model.
Quick Reference
Indentation Rules
| Rule | Detail |
|---|---|
| Indentation character | Space only |
| Tabs | Forbidden for indentation |
| Depth per level | Any consistent number (2 common) |
| Sibling alignment | Must be identical |
| Child indentation | Must be greater than parent |
Key-Value Syntax
| Pattern | Valid | Notes |
|---|---|---|
key: value | Yes | Colon followed by space |
key:value | No | Parsed as a single scalar |
key: "a:b" | Yes | Quoted colon in value |
key: a:b | No | Unquoted colon trap |
Block Scalars
| Indicator | Behavior |
|---|---|
| | Preserves newlines |
> | Folds newlines to spaces |
|2 | Explicit indentation indicator |
Best Practices
โ Do This:
# Use spaces, two per level
server:
host: localhost # โ
# Quote values with colons
url: "postgres://user:pass@host:5432/db" # โ
# Align siblings exactly
ports:
- "80:80"
- "443:443" # โ
# Use literal block for scripts
script: |
echo "hello" # โ
โ Don’t Do This:
# Tab indentation
server:
host: localhost # โ
# Unquoted colon in value
url: postgres://user:pass@host:5432/db # โ
# Misaligned sibling
ports:
- "80:80"
- "443:443" # โ
# Inconsistent indentation depth
a:
b: 1
c: 2 # โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| “Mapping values not allowed” | Unquoted colon in value | Quote the value |
| “Found character that cannot start” | Tab used for indentation | Replace tabs with spaces |
| Key parsed as child | Sibling indentation off by one space | Align siblings exactly |
| Block scalar content re-indented | Missing explicit indicator | Use |2 or >2 |
| Inconsistent parse across editors | Tab width differs | Configure editor to insert spaces |
Real-World Examples
1. Two-space nesting
server:
host: localhost
port: 8080
2. Quoted URL
url: "postgres://user:pass@host:5432/db"
3. Literal script
script: |
#!/bin/bash
echo "start"
4. Folded description
description: >
A long sentence that
becomes one line.
5. Block sequence
items:
- one
- two
6. Nested mapping
app:
database:
host: db
7. Explicit indentation indicator
source: |2
indented
8. Quoted time
start: "10:30"
9. Aligned siblings
a: 1
b: 2
10. Comment with tab allowed
key: value # tab inside comment is fine
Visual
Indentation Defines Structure
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ INDENTATION AS STRUCTURE โ
โ โ
โ server: โ
โ host: localhost โ child of server โ
โ port: 8080 โ sibling of host โ
โ โ
โ database: โ sibling of server โ
โ host: db โ child of database โ
โ โ
โ Two spaces = one level โ
โ Same column = sibling โ
โ Deeper column = child โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Tab Problem
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ WHY TABS BREAK YAML โ
โ โ
โ Editor A: tab = 2 columns โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ key: โ โ
โ โ โโvalue โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Editor B: tab = 4 columns โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ key: โ โ
โ โ โโโโvalue โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Spec: tabs forbidden for indentation โ
โ Fix: configure editor to insert spaces โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The Colon Trap
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ COLON AS SEPARATOR โ
โ โ
โ url: postgres://user:pass@host:5432/db โ
โ โ โ
โ โโโโบ parser reads this colon as a key separator โ
โ โ โ
โ โผ โ
โ "postgres://user" is the value โ
โ ":pass" starts a new mapping โ ERROR โ
โ โ
โ Fix: quote the value โ
โ url: "postgres://user:pass@host:5432/db" โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Block Scalar Behavior
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ | vs > โ
โ โ
โ literal: | โ
โ Line one. โ
โ Line two. โ
โ โ "Line one.\nLine two.\n" โ
โ โ
โ folded: > โ
โ Line one. โ
โ Line two. โ
โ โ "Line one. Line two.\n" โ
โ โ
โ | preserves newlines; > joins with spaces โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Summary
| Item | Value |
|---|---|
| Indentation character | Space only |
| Tabs | Forbidden for indentation |
| Common depth | Two spaces per level |
| Key-value syntax | key: value (colon + space) |
| Colon trap | Quote values containing colons |
| Literal block | | preserves newlines |
| Folded block | > joins lines with spaces |
| Explicit indicator | |2 when inference fails |
| Sibling rule | Identical indentation |
Key takeaways:
- Indentation is the syntax. YAML has no closing braces or tags; the nesting you see is the nesting the parser reads. The amount of indentation is convention; the consistency is requirement .
- Tabs are forbidden for indentation. The specification prohibits them because tab width varies across systems, making files non-portable . Configure your editor to insert spaces.
- A colon must be followed by a space to separate key from value. Values containing colons must be quoted, or the parser reads the colon as a structural separator and fails .
|and>control newline behavior. The pipe preserves them; the fold replaces single newlines with spaces. The indentation under the indicator must be consistent .- Most YAML errors are invisible whitespace errors. Check for tabs, check sibling alignment, and quote values with colons before guessing at anything else.
Remember: YAML’s syntax is small but unforgiving. The structure is the indentation, and the indentation is spaces only. A tab where a space was expected, one extra space before a sibling, or an unquoted colon in a URL will break the parse with an error that points to a line that looks fine. The discipline is to treat whitespace as syntax: use spaces, align siblings exactly, quote ambiguous values, and validate the file before deploying it. The format is designed for human readability; the failures come from human eyes missing what the parser sees.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!