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

PitfallExampleFix
Unquoted Jinja2var: {{ x }}var: "{{ x }}"
Tab indentation\tname: taskUse spaces
Missing colonansible.builtin.copyansible.builtin.copy:
Unquoted colonmsg: key: valuemsg: "key: value"
Unquoted *name: *name: "*"
Boolean stringson, yes, offQuote if literal string intended

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.