YAML (YAML Ain't Markup Language) is a human-readable data serialization format widely used for configuration files, especially in DevOps tools like Kubernetes, Docker Compose, and CI/CD pipelines. This comprehensive guide covers YAML validation, formatting, common errors, and best practices.
YAML validation is the process of checking whether a YAML file conforms to proper syntax rules and structure. A YAML validator parses the file and identifies errors like incorrect indentation, invalid characters, or structural problems that would cause parsing failures.
Unlike JSON, which has strict syntax rules enforced by most text editors, YAML's flexibility and reliance on whitespace make it prone to subtle errors that are difficult to spot manually.
YAML validation is critical for several reasons:
Understanding YAML syntax is essential for writing valid configuration files.
YAML uses key-value pairs, lists, and nested structures:
# Key-value pairs
name: John Doe
age: 30
active: true
# Lists
fruits:
- apple
- banana
- orange
# Nested objects
person:
name: Jane Smith
address:
street: 123 Main St
city: Boston
country: USA
YAML uses indentation to denote structure. These rules are critical:
# Correct indentation
server:
host: localhost
port: 8080
ssl:
enabled: true
certificate: /path/to/cert
# Incorrect - mixing indentation levels
server:
host: localhost
port: 8080 # Error: inconsistent indentation
YAML supports various data types with automatic type inference:
# Strings
name: John Doe
quoted: "Hello World"
multiline: |
This is a
multiline string
# Numbers
integer: 42
float: 3.14
octal: 0o755
hex: 0xFF
# Booleans
enabled: true
disabled: false
yes_value: yes
no_value: no
# Null values
nothing: null
tilde: ~
# Dates
date: 2026-03-12
datetime: 2026-03-12T10:30:00Z
The most common YAML error is incorrect indentation:
# Error: Inconsistent indentation
config:
database:
host: localhost
port: 5432 # Only 1 space instead of 2
# Fix: Consistent 2-space indentation
config:
database:
host: localhost
port: 5432
YAML spec prohibits tabs for indentation:
# Error: Using tab character
config:
→ database: postgres # Tab character (shown as →)
# Fix: Use spaces
config:
database: postgres
Key-value pairs require colons:
# Error: Missing colon
name John Doe
# Fix: Add colon after key
name: John Doe
Special characters require quotes:
# Error: Unquoted special characters
message: Hello: World # Colon needs quoting
path: C:\Users\John # Backslash needs quoting
# Fix: Quote strings with special characters
message: "Hello: World"
path: "C:\\Users\\John"
Keys at the same level must be unique:
# Error: Duplicate key
config:
port: 8080
host: localhost
port: 9000 # Duplicate
# Fix: Use unique keys
config:
http_port: 8080
host: localhost
admin_port: 9000
List items must use proper dash syntax:
# Error: Missing space after dash
items:
-apple
-banana
# Fix: Add space after dash
items:
- apple
- banana
Don't mix list and mapping at the same level:
# Error: Mixing list and map
data:
- item1
key: value # Can't mix
# Fix: Choose one structure
data:
items:
- item1
key: value
Multiline strings require proper indicators:
# Literal block (preserves newlines)
description: |
Line 1
Line 2
Line 3
# Folded block (folds newlines to spaces)
summary: >
This is a long
text that will be
folded into a single line
Use 2 spaces for indentation throughout your YAML files:
application:
server:
port: 8080
host: 0.0.0.0
database:
url: postgres://localhost
pool:
min: 5
max: 20
Add comments to explain complex configurations:
# Database connection settings
database:
# Production database URL
url: postgres://prod-db:5432/myapp
# Connection pool configuration
pool:
min: 10 # Minimum connections
max: 50 # Maximum connections
Group related configurations together:
# Server configuration
server:
host: localhost
port: 8080
timeout: 30
# Database configuration
database:
host: db.example.com
port: 5432
name: myapp
# Logging configuration
logging:
level: info
format: json
Avoid duplication with YAML anchors:
# Define anchor
defaults: &defaults
timeout: 30
retries: 3
ssl: true
# Use alias
production:
<<: *defaults
host: prod.example.com
staging:
<<: *defaults
host: staging.example.com
Quote strings containing special characters or to enforce string type:
# Force string type (not number)
version: "1.0"
# Special characters
message: "Hello: World"
# Leading/trailing spaces
text: " padded text "
# YAML keywords as values
value: "yes" # String, not boolean
Understanding the differences helps choose the right format:
# YAML
person:
name: John Doe
age: 30
skills:
- JavaScript
- Python
- Go
// JSON equivalent
{
"person": {
"name": "John Doe",
"age": 30,
"skills": [
"JavaScript",
"Python",
"Go"
]
}
}
Kubernetes heavily relies on YAML for resource definitions:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
Docker Compose uses YAML for multi-container applications:
version: '3.8'
services:
web:
build: .
ports:
- "8080:80"
depends_on:
- db
environment:
- DATABASE_URL=postgres://db:5432/myapp
db:
image: postgres:14
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_PASSWORD=secret
volumes:
db-data:
CI/CD workflows use YAML for pipeline definitions:
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm test
Ansible uses YAML for automation playbooks:
---
- name: Configure web servers
hosts: webservers
become: yes
tasks:
- name: Install nginx
apt:
name: nginx
state: present
- name: Start nginx service
service:
name: nginx
state: started
enabled: yes
Reuse configuration blocks with anchors (&) and aliases (*):
# Define base configuration
base_config: &base
timeout: 30
retries: 3
log_level: info
# Reuse in multiple places
service_a:
<<: *base
url: https://api-a.example.com
service_b:
<<: *base
url: https://api-b.example.com
retries: 5 # Override specific value
Combine multiple anchors:
defaults: &defaults
timeout: 30
retries: 3
auth: &auth
username: admin
password: secret
production:
<<: [*defaults, *auth]
host: prod.example.com
Use question mark syntax for complex keys:
? - key1
- key2
: value
? [complex, key]
: another value
QuickUtil.dev's YAML Validator offers:
Popular CLI tools for YAML validation:
# yamllint - Python-based YAML linter
pip install yamllint
yamllint config.yaml
# yq - YAML processor (like jq for YAML)
brew install yq
yq eval '.server.port' config.yaml
# kubectl for Kubernetes YAML
kubectl apply --dry-run=client -f manifest.yaml
IDE extensions for YAML validation:
Common error messages and their meanings:
# "mapping values are not allowed here"
# Cause: Missing space after colon or improper indentation
key:value # Error
key: value # Correct
# "could not find expected ':'"
# Cause: Missing colon in key-value pair
name John # Error
name: John # Correct
# "found character that cannot start any token"
# Cause: Tab character or invalid character
→key: value # Error (tab character)
key: value # Correct
# "duplicate key"
# Cause: Same key appears twice at same level
port: 8080
port: 9000 # Error
Be aware of YAML bombs that can cause denial of service:
# Billion Laughs Attack example
a: &a ["lol","lol","lol","lol","lol","lol","lol","lol","lol"]
b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]
c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]
# This expands to billions of elements
Use safe loading methods in your code:
# Python - use safe_load instead of load
import yaml
with open('config.yaml') as f:
config = yaml.safe_load(f) # Safe
# config = yaml.load(f) # Unsafe - allows arbitrary code execution
Never commit sensitive data in YAML files:
# Bad - hardcoded credentials
database:
password: MySecretPassword123
# Good - use environment variables
database:
password: ${DATABASE_PASSWORD}
# Better - use secret management
database:
password: !vault |
$ANSIBLE_VAULT;1.1;AES256
...
YAML validation is essential for maintaining reliable configuration files in modern DevOps workflows. By understanding YAML syntax rules, using validation tools, and following best practices, you can avoid common errors and create maintainable configuration files.
Regular validation catches errors early, improves team collaboration, and prevents deployment failures. Use tools like QuickUtil.dev's YAML Validator to ensure your YAML files are always syntactically correct and properly formatted.
Paste your YAML into a YAML validator tool to check for syntax errors, indentation issues, and structural problems. The validator will highlight errors and provide suggestions for fixing them.
Common errors include incorrect indentation, mixing tabs and spaces, missing colons, improper quotes, duplicate keys, and invalid characters in keys or values.
Use consistent spacing (typically 2 spaces) for each indentation level. Never use tabs. Ensure child elements are indented further than their parents. Use a YAML formatter to auto-fix indentation.
Yes, YAML formatters automatically fix indentation, align values, and standardize spacing while preserving the data structure and comments.
YAML is more human-readable with less syntax overhead, supports comments, and uses indentation instead of brackets. JSON is more strict, widely supported, and better for data interchange.
Use quotes for strings containing special characters like colons, hashes, brackets, or leading/trailing spaces. Single quotes preserve literal strings; double quotes allow escape sequences.
Always use spaces, never tabs. YAML spec prohibits tabs for indentation. Most linters recommend 2 spaces per indentation level for consistency.
Use a YAML validator to check syntax first, then use kubectl --dry-run or specialized Kubernetes validators to check against schema requirements and API versions.
Stop struggling with YAML syntax errors. Use our free YAML Validator to check syntax, format files, and fix errors in seconds.
Try the YAML Validator Now