Yaml Syntax Reference

Comprehensive reference for yaml syntax reference covering essential concepts, practical examples, and production best practices.

YAML Syntax Reference

YAML (YAML Ain’t Markup Language) is a data serialization format designed for human readability and machine parseability. It appears wherever configuration, manifests, or pipeline definitions are authored outside of a programming language: Kubernetes resource files, Ansible playbooks, CI/CD pipeline definitions, Docker Compose files, and internal tooling configs. This reference covers the syntax itself—not tool-specific workflows, not language bindings, and not the semantics of any particular consumer. If you are editing a YAML file and seeing parse errors, unexpected type coercion, or indentation-related failures, this is the reference you open.

Defining Scalars

A scalar is a single value: string, integer, float, boolean, or null. YAML distinguishes these by context and quoting, but the parser’s default behaviour is strict.

Unquoted string

service_name: api-gateway

Integer

replica_count: 3

Float

timeout_seconds: 4.5

Boolean – YAML 1.1 and 1.2 accept several plain‑text equivalents, but they are not interchangeable with the strings "true" or "false".

enabled: true

Null – three spellings are accepted; all resolve to null in the constructed object.

parent: ~

or

parent: null

or

parent: ""

(An unquoted empty value is *not* null; it is a missing key.)

String that looks like a boolean or number – always quote if you intend it as text.

status: "true"
version: "3.2"

Structuring Mappings and Sequences

A mapping is a set of key–value pairs. A sequence is an ordered list. Most YAML documents combine both.

Mapping

database:
  host: localhost
  port: 5432
  ssl: false

Sequence (block style)

environments:
  - development
  - staging
  - production

Sequence (flow style)

features: [auth, logging, metrics]

Nested mapping inside a sequence

services:
  - name: web
    port: 8080
  - name: api
    port: 3000

Key ordering is not guaranteed by the spec, but most parsers preserve insertion order when using safe_load or safe_dump. If order matters for downstream consumers, verify the specific tool’s behaviour.

Advanced Syntax: Anchors, Aliases, and Tags

Anchors allow a node to be defined once and referenced elsewhere. Aliases pull in the anchored node. Tags override or specify a type.

Anchor and alias

&db_default
database:
  host: localhost
  port: 5432

development:
  <<: *db_default
  name: dev_db

production:
  <<: *db_default
  name: prod_db

Here <<: merges the anchored mapping into the current context. The * syntax pulls the alias forward. If two anchors define the same key, the closer definition wins.

Tag override

!!str "hello world"

The !!str tag forces the scalar to be interpreted as a string, even if the parser would otherwise coerce it. In YAML 1.1, !!str is the default for values that look like strings; in YAML 1.2, all scalars default to string unless another tag matches.

Custom tags can be defined in a schema, but they are rarely needed in general-purpose config. If you see !!python/object/apply:... in a file you did not write, it indicates a deserialization risk.

When It Silently Fails – Sharp Edges

Indentation and Whitespace

YAML is sensitive to leading whitespace. Tabs are discouraged; the spec says they should be expanded as 2 spaces, but many parsers diverge.

*Exact failure*: A file containing a single tab character for indentation under apiVersion: in a Kubernetes manifest produces:

error: mapping values are not allowed here

The parser has consumed the previous key’s value and hit the tab before the next key:, which it interprets as a new mapping entry in an invalid position.

Rule: Use 2-space indentation. Never mix tabs and spaces. Most linters (yamllint, prettier with YAML plugin) will flag this immediately.

Quoting and Type Coercion

YAML’s default type coercion is the most common source of production bugs.

flag: yes

yes coerces to true. Similarly no → false, on → true, off → false. If a downstream service expects the string "yes" (e.g., as a feature flag passed to an environment variable), the coercion breaks the flow.

*Exact result*: Running python3 -c "import yaml; print(yaml.safe_load('flag: yes'))" returns {'flag': True}. Running the same with flag: "yes" returns {'flag': 'yes'}.

Never rely on implicit coercion for user‑controlled or externally sourced YAML. Always quote values that should remain strings.

Flow‑style Collections with Nested Structure

Flow style ({} and []) does not support multi‑line nesting. Attempting to mix flow and block styles in the same mapping often produces a parse error that is not obvious.

# ❌ Invalid – flow style inside a block mapping
services:
  { name: web, port: 8080 }

Most parsers reject this outright:

yaml.parser.ParserProblem: while parsing a block mapping
  in "<string>", line 2, column 5
  could not find expected ':'"

If you need flow style, keep the mapping entirely in flow syntax, or entirely in block syntax.

Duplicate Keys

The YAML spec says behaviour on duplicate keys is undefined. parsers typically overwrite the first value with the last, but this is implementation‑dependent.

x: 1
x: 2

python3 -c "import yaml; print(yaml.safe_load('x: 1\nx: 2'))" returns {'x': 2}. A Go YAML library might raise an error or return the first value. Never depend on a specific behaviour; deduplicate keys before parsing if uniqueness is required.

Validation, Parsing, and Error Messages

Concrete commands for the most common workflows.

Python (stdlib yaml)

python3 -c "import yaml, sys; print(yaml.safe_load(sys.stdin))" < config.yaml

If the file contains a syntax error, the command aborts with:

yaml.scanner.ScannerError: mapping values are not allowed here
  in "<string>", line 1, column 1

Python – strict mode, dump + load round‑trip

python3 -c "
import yaml, json, sys
data = yaml.safe_load(open('config.yaml'))
print(json.dumps(data, indent=2))
" 2>&1 | head -20

This catches type‑coercion issues that survive a safe‑load, because json.dumps will fail on non‑JSON‑compatible types (e.g., Python datetime objects, which yaml.safe_load can produce if a !!timestamp tag is present).

yq (Go-based, commonly used in shells)

yq eval '.' config.yaml

If the file is valid YAML, yq prints the parsed structure to stdout. If there is a syntax error:

error: parse error: while parsing indicator

yq does not attempt type coercion; it either parses or fails.

JSON‑YAML conversion sanity check

python3 -c "
import yaml, json
yaml_str = open('config.yaml').read()
data = yaml.safe_load(yaml_str)
print(json.loads(json.dumps(data)))
" 

If this succeeds, the YAML is both valid and round‑trip safe through JSON (i.e., no Python‑specific types leaked in).

YAML 1.1 vs 1.2 Behaviour Differences

The two versions ship with different default tags and type‑coercion rules. Most modern tools default to 1.2, but legacy configs may declare yaml-1.1 via a document header.

YAML 1.1 defaults

YAML 1.2 defaults

How to declare the version (rarely needed, but concrete):

%YAML 1.1
---

or

%YAML 1.2
---

If your tooling is mixing versions (e.g., a Kubernetes cluster that parses 1.1 but your CI pipeline validates 1.2), you may see different type coercion on the same key. Pin the version at the top of the file if you must control behaviour, and document which version your consumers expect.

Quick Reference Cheat Sheet

ConstructSyntaxNotes
String (unquoted)key: valueNo quotes needed if no special chars
String (quoted)key: "value" or key: 'value'Use when value looks like boolean/number
Integerkey: 42
Float`key:

This page was rewritten on 10 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.