YAML Linting Best Practices: Catch Errors Before Deploy
A misplaced space in a YAML file can bring down a production deployment. Unlike JSON, which fails loudly on syntax errors, YAML can silently parse incorrect indentation into unexpected data structures. Linting catches these issues before they reach production.
Why Lint YAML?
YAML's flexibility is both its strength and weakness:
# This is valid YAML but probably wrong
ports:
- 80
- 443
name: webserver # This is a key in the SECOND list item, not the mapping!
The above creates a list where the second item is a mapping {443: null, name: webserver}. A linter would catch this indentation issue. Without linting, this kind of bug can take hours to diagnose.
yamllint: The Standard Linter
yamllint is the most widely used YAML linter. It checks both syntax validity and style consistency.
Installation
pip install yamllint
Basic Usage
# Lint a single file
yamllint config.yaml
# Lint a directory
yamllint .
# Lint with a specific config
yamllint -c .yamllint.yml .
Configuration
Create .yamllint.yml in your project root:
extends: default
rules:
line-length:
max: 120
level: warning
indentation:
spaces: 2
indent-sequences: true
truthy:
allowed-values: ['true', 'false', 'yes', 'no']
comments:
require-starting-space: true
min-spaces-from-content: 2
document-start: disable
empty-lines:
max: 1
Key Rules Explained
| Rule | Purpose | Recommended Setting |
|---|---|---|
indentation | Enforce consistent indentation | 2 spaces, no tabs |
line-length | Prevent overly long lines | 120 chars (warning) |
truthy | Control boolean values | true/false only |
comments | Comment formatting | Require space after # |
document-start | Require --- at start | Disable (optional) |
trailing-spaces | No trailing whitespace | Enable |
new-line-at-end-of-file | Consistent file endings | Enable |
Common Errors Caught by Linting
1. Tab Characters
YAML forbids tabs for indentation, but editors sometimes insert them:
# ERROR: tab character
server:
port: 8080 # Tab instead of spaces!
2. Inconsistent Indentation
# ERROR: mixing 2 and 4 space indentation
database:
host: localhost
port: 5432 # Wrong: 4 spaces instead of 2
3. Duplicate Keys
# ERROR: duplicate key (second silently overrides first)
server:
port: 8080
host: localhost
port: 9090 # Duplicate! Which port is used?
4. Trailing Spaces
Invisible trailing spaces can cause surprising behavior, especially in multiline strings. A linter flags these immediately.
Quick validation without installing anything: paste your YAML into our YAML Validator.
CI/CD Integration
GitHub Actions
name: YAML Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install yamllint
run: pip install yamllint
- name: Lint YAML files
run: yamllint .
Pre-commit Hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/adrienverge/yamllint
rev: v1.33.0
hooks:
- id: yamllint
args: [-c, .yamllint.yml]
pip install pre-commit
pre-commit install
Now YAML is automatically linted before every commit.
GitLab CI
yaml-lint:
image: python:3.12-slim
script:
- pip install yamllint
- yamllint .
rules:
- changes:
- "**/*.yaml"
- "**/*.yml"
Editor Integration
Most editors support real-time YAML linting:
- VS Code: Install the "YAML" extension by Red Hat (uses yamllint)
- Vim/Neovim: Use ALE or coc-yaml
- JetBrains IDEs: Built-in YAML support with configurable inspections
Enable format-on-save for YAML files to automatically fix whitespace issues.
Tool-Specific Linting
Generic YAML linting catches syntax errors, but tool-specific linters validate semantic correctness:
Kubernetes
# kubeval - validate against K8s schemas
kubeval deployment.yaml
# kubeconform - faster alternative
kubeconform -strict deployment.yaml
Docker Compose
docker compose config --quiet
GitHub Actions
# actionlint - validates workflow syntax
actionlint .github/workflows/*.yml
Ansible
ansible-lint playbook.yml
For a deeper understanding of YAML syntax rules, see our YAML syntax tutorial.
Best Practices Summary
- Add yamllint to CI β Every YAML change should pass linting
- Use pre-commit hooks β Catch errors before they reach the repository
- Standardize on 2-space indentation β The DevOps convention
- Disable the truthy rule or restrict it β The
yes/noboolean problem causes real bugs - Set a reasonable line length β 120 characters covers most cases
- Use tool-specific validators β Generic linting plus K8s/Docker/Actions-specific validation
- Configure your editor β Real-time feedback is faster than CI failures
FAQ
Should I use YAML or JSON for configuration files?
YAML is preferred for human-edited configuration files due to its readability, comment support, and concise syntax. JSON is better for machine-generated data and API communication. For a detailed comparison, see our YAML vs JSON guide.
How do I handle yamllint warnings vs errors?
Configure critical rules (indentation, syntax) as errors that block CI. Set style rules (line-length, comments) as warnings that appear but don't block. This balances strictness with developer productivity.
Related Resources
- YAML Validator β Validate YAML syntax online instantly
- YAML Syntax Tutorial β Learn YAML from scratch
- YAML for Docker Compose β Docker-specific YAML patterns