Introduction
Rule 911 (syntax-check) is ansible-lint's most critical rule — it's unskippable. If your playbook fails ansible-playbook --syntax-check, no other linting rules are evaluated. This guide covers the most common syntax errors and how to fix each one.
The Rule
Rule 911 runs ansible-playbook --syntax-check on every playbook. If syntax validation fails, all further linting stops. You cannot skip it:
# .ansible-lint — this does NOT work for rule 911
skip_list:
- syntax-check # Ignored — rule is unskippable
Common Syntax Errors
1. Undefined Variable in hosts
Error:
---
- name: Deploy application
hosts: "{{ my_hosts }}"
tasks: []
syntax-check[specific]: The field 'hosts' has an invalid value, which includes
an undefined variable. 'my_hosts' is undefined.
Fix: Add a default() filter:
---
- name: Deploy application
hosts: "{{ my_hosts | default([]) }}"
tasks: []
Or define the variable in inventory/group_vars.
2. Bad YAML Indentation
Error:
---
- name: My playbook
hosts: all
tasks:
- name: Install package
ansible.builtin.yum: # ← Wrong indentation
name: nginx
Fix: Align module under the task:
---
- name: My playbook
hosts: all
tasks:
- name: Install package
ansible.builtin.yum:
name: nginx
3. Missing Colon After Module Name
Error:
- name: Copy file
ansible.builtin.copy
src: file.txt
dest: /tmp/file.txt
Fix: Add the colon:
- name: Copy file
ansible.builtin.copy:
src: file.txt
dest: /tmp/file.txt
4. Tab Characters
YAML doesn't allow tabs for indentation:
- name: My task
ansible.builtin.debug: # ← TAB character
msg: "hello"
Fix: Replace tabs with spaces (2-space indentation is standard).
5. Duplicate Keys
- name: Configure server
hosts: all
become: true
become: false # ← Duplicate key
Fix: Remove the duplicate.
6. Missing Quotes Around Special Characters
- name: Show message
ansible.builtin.debug:
msg: This has a : colon that breaks YAML # ← Unquoted colon
Fix: Quote the string:
- name: Show message
ansible.builtin.debug:
msg: "This has a : colon that works fine"
7. Incorrect Variable Syntax
- name: Set variable
ansible.builtin.set_fact:
my_var: {{ some_value }} # ← Missing quotes around Jinja2
Fix: Always quote Jinja2 expressions:
- name: Set variable
ansible.builtin.set_fact:
my_var: "{{ some_value }}"
How to Run Syntax Check
Manual Check
# Check single playbook
ansible-playbook --syntax-check playbook.yml
# Check with inventory
ansible-playbook --syntax-check -i inventory playbook.yml
# Check all playbooks
for f in *.yml; do ansible-playbook --syntax-check "$f"; done
In CI/CD Pipeline
# .github/workflows/lint.yml
- name: Syntax check
run: |
ansible-playbook --syntax-check site.yml
ansible-lint site.yml
With ansible-lint
# Runs syntax-check automatically as first step
ansible-lint playbook.yml
Pre-commit Hook
# .pre-commit-config.yaml
repos:
- repo: https://github.com/ansible/ansible-lint
rev: v6.22.1
hooks:
- id: ansible-lint
files: \.(yml|yaml)$
Debugging Tips
Use --syntax-check with Verbose
ansible-playbook --syntax-check -vvv playbook.yml
Validate YAML First
# Python YAML validator
python3 -c "import yaml; yaml.safe_load(open('playbook.yml'))"
# yamllint
yamllint playbook.yml
Common yamllint Configuration
# .yamllint
---
extends: default
rules:
line-length:
max: 160
truthy:
allowed-values: ['true', 'false', 'yes', 'no']
Quick Reference: YAML Pitfalls
| Pitfall | Example | Fix |
|---|---|---|
| Unquoted Jinja2 | var: {{ x }} | var: "{{ x }}" |
| Tab indentation | \tname: task | Use spaces |
| Missing colon | ansible.builtin.copy | ansible.builtin.copy: |
| Unquoted colon | msg: key: value | msg: "key: value" |
Unquoted * | name: * | name: "*" |
| Boolean strings | on, yes, off | Quote if literal string intended |
Related Articles
- Ansible-Lint Guide
- literal-compare Rule (601)
- no-log-password Rule
- Ansible Best Practices Guide
- Ansible Debug Module Guide
Conclusion
Rule 911 is unskippable because everything depends on valid syntax. Run ansible-playbook --syntax-check before every commit. The most common causes: undefined variables in hosts (fix with default()), bad YAML indentation (use 2-space, no tabs), unquoted Jinja2 expressions, and missing colons. Add syntax checking to your CI/CD pipeline and pre-commit hooks to catch errors before they reach production.