| | |

YAML 02 ๐Ÿ“„ Syntax Fundamentals and Significant Indentation Rules

โฑ๏ธ Estimated read: 9 min | |

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

RuleDetail
Indentation characterSpace only
TabsForbidden for indentation
Depth per levelAny consistent number (2 common)
Sibling alignmentMust be identical
Child indentationMust be greater than parent

Key-Value Syntax

PatternValidNotes
key: valueYesColon followed by space
key:valueNoParsed as a single scalar
key: "a:b"YesQuoted colon in value
key: a:bNoUnquoted colon trap

Block Scalars

IndicatorBehavior
|Preserves newlines
>Folds newlines to spaces
|2Explicit 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

PitfallWhy It HappensFix
“Mapping values not allowed”Unquoted colon in valueQuote the value
“Found character that cannot start”Tab used for indentationReplace tabs with spaces
Key parsed as childSibling indentation off by one spaceAlign siblings exactly
Block scalar content re-indentedMissing explicit indicatorUse |2 or >2
Inconsistent parse across editorsTab width differsConfigure 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

ItemValue
Indentation characterSpace only
TabsForbidden for indentation
Common depthTwo spaces per level
Key-value syntaxkey: value (colon + space)
Colon trapQuote values containing colons
Literal block| preserves newlines
Folded block> joins lines with spaces
Explicit indicator|2 when inference fails
Sibling ruleIdentical 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.

Was this helpful?


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!