Introduction
YAML syntax errors are among the most common Ansible failures. When a playbook contains malformed YAML, Ansible cannot parse it and fails immediately before any task executes. These errors stem from YAML's strict indentation rules, special character handling, quoting requirements, and the interaction between YAML syntax and Jinja2 templating.
The error messages can be cryptic, often pointing to the wrong line number due to how YAML parsers work. Understanding common YAML pitfalls and using proper validation tools helps quickly identify and fix these issues.
Symptoms
Basic YAML syntax errors:
```bash $ ansible-playbook site.yml ERROR! Syntax Error while loading YAML. did not find expected '-' indicator
The error appears to be in 'site.yml': line 15, column 5, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
tasks: - name: Install nginx ^ here ```
Indentation errors:
```bash $ ansible-playbook deploy.yml ERROR! Syntax Error while loading YAML. mapping values are not allowed in this context
The error appears to be in 'deploy.yml': line 23, column 12
The offending line appears to be:
- name: Configure app
- template:
- src: app.conf.j2
- dest: /etc/app/app.conf
- ^ here
`
Jinja2 template quoting issues:
```bash $ ansible-playbook config.yml ERROR! Syntax Error while loading YAML. found unexpected end of stream
The error appears to be in 'config.yml': line 45
The offending line appears to be:
- debug: msg={{ ansible_hostname }}
- ^ here
`
Missing colon errors:
```bash $ ansible-playbook site.yml ERROR! Syntax Error while loading YAML. could not find expected ':'
The offending line appears to be:
- name Start service
- ^ here
`
Complex Jinja2 expression issues:
```bash $ ansible-playbook complex.yml ERROR! Syntax Error while loading YAML. template error while templating string: unexpected char '$' at 15
The offending line appears to be:
value: "{{ $var }}" ^ here ```
Common Causes
1. Tab Characters Mixed with Spaces
YAML forbids tab characters for indentation:
# WRONG - contains tabs
- name: Install package
yum:
name: nginx # This line uses a tab!
state: present2. Inconsistent Indentation
YAML requires consistent indentation levels:
# WRONG - inconsistent indentation
- name: Deploy app
tasks:
- name: Copy files
copy:
src: app/
dest: /opt/app/ # One space less than previous line3. Unquoted Special Characters
Colons, hashes, and other special characters need quoting:
```yaml # WRONG - unquoted value with colon - set_fact: message: This is a test: value
# CORRECT - set_fact: message: "This is a test: value" ```
4. Improper Jinja2 Syntax
Jinja2 expressions must be properly enclosed:
```yaml # WRONG - missing closing braces - debug: msg: "{{ item.name "
# WRONG - nested braces incorrectly - debug: msg: "{{ {{ item.name }} }}" ```
5. List vs Dict Confusion
Mixing list and dict syntax:
# WRONG - dict item in list
tasks:
- name: Task one
command: echo "one"
name: Task two # Missing dash!
command: echo "two"6. Multiline String Issues
Incorrect multiline string format:
# WRONG - literal block scalar with wrong indicator
- shell: |
echo "line one"
echo "line two" # Wrong indentation for blockStep-by-Step Fix
Step 1: Run Syntax Check
Validate playbook syntax:
```bash # Basic syntax check ansible-playbook --syntax-check playbook.yml
# With more detail ansible-playbook --syntax-check playbook.yml -vv
# Use yamllint for detailed YAML validation pip install yamllint yamllint playbook.yml
# Check all playbooks in directory yamllint roles/*.yml playbooks/*.yml ```
Step 2: Check for Tab Characters
Find and fix tab characters:
```bash # Find tabs in playbook grep -P '\t' playbook.yml
# Or with cat -A (shows tabs as ^I) cat -A playbook.yml | grep '\^I'
# Replace tabs with spaces sed -i 's/\t/ /g' playbook.yml
# In Vim, convert tabs to spaces :set expandtab :retab ```
Step 3: Fix Indentation Issues
Use proper indentation (2 spaces is Ansible convention):
# Correct indentation pattern
---
- name: Play name
hosts: all
vars:
var1: value1
var2: value2
tasks:
- name: Task name
module_name:
parameter1: value1
parameter2: value2
notify:
- handler_name
handlers:
- name: handler_name
module_name:
parameter: valueConfigure editor for YAML indentation:
```yaml # .editorconfig root = true
[*.yml] indent_style = space indent_size = 2
[*.yaml] indent_style = space indent_size = 2 ```
Step 4: Fix Jinja2 Template Quoting
Properly quote Jinja2 expressions:
```yaml # WRONG - unquoted Jinja2 - debug: msg={{ item }} when: item == true
# CORRECT - quoted Jinja2 - debug: msg: "{{ item }}" when: item == true
# WRONG - special characters - set_fact: url: http://{{ host }}:{{ port }}/api
# CORRECT - quote the entire value - set_fact: url: "http://{{ host }}:{{ port }}/api"
# WRONG - colon in string - set_fact: message: Status: OK
# CORRECT - set_fact: message: "Status: OK" ```
Step 5: Fix Multiline Strings
Use correct multiline string formats:
```yaml # Literal block scalar (preserves newlines) - shell: | echo "line one" echo "line two" echo "line three"
# Folded block scalar (newlines become spaces) - debug: msg: > This is a very long message that will be folded into a single line when parsed.
# Literal with strip (removes trailing newline) - shell: |- echo "no trailing newline"
# Literal with keep (preserves trailing newlines) - shell: |+ echo "preserves trailing newlines" ```
Step 6: Fix List and Dict Syntax
Use correct collection syntax:
```yaml # List of tasks tasks: - name: First task command: echo "first" - name: Second task command: echo "second"
# List of values vars: my_list: - item1 - item2 - item3
# Dictionary vars: my_dict: key1: value1 key2: value2
# List of dictionaries vars: my_list_of_dicts: - name: item1 value: 100 - name: item2 value: 200 ```
Step 7: Use ansible-lint for Comprehensive Checks
Install and run ansible-lint:
```bash # Install ansible-lint pip install ansible-lint
# Run lint ansible-lint playbook.yml
# With specific rules ansible-lint --exclude=106 playbook.yml
# Show rule documentation ansible-lint -L
# Fix automatically where possible ansible-lint --fix playbook.yml ```
Create ansible-lint configuration:
```yaml # .ansible-lint exclude_paths: - .github/ - tests/
skip_list: - yaml[colons] # Skip specific rule
enable_list: - name[play] # Enable additional rules
rulesdir: - ./custom_rules/ ```
Step 8: Debug Complex Syntax Issues
Isolate the problematic section:
# Create minimal test playbook
---
- name: Test playbook
hosts: localhost
gather_facts: false
tasks:
# Paste problematic section here
- debug:
msg: "test"Use Python YAML parser directly:
```python #!/usr/bin/env python3 import yaml import sys
with open(sys.argv[1], 'r') as f: try: data = yaml.safe_load(f) print("YAML is valid") print(yaml.dump(data, default_flow_style=False)) except yaml.YAMLError as e: print(f"YAML error: {e}") ```
Verification
After fixing syntax errors:
```bash # Run syntax check ansible-playbook --syntax-check playbook.yml # Should show: playbook.yml: OK
# Run yamllint yamllint playbook.yml # Should show no errors
# Run ansible-lint ansible-lint playbook.yml # Should show no errors (or only warnings)
# Try running the playbook ansible-playbook playbook.yml --check # Should execute without syntax errors
# Verify specific tasks ansible-playbook playbook.yml --list-tasks # Should list all tasks correctly ```
Test in isolated environment:
```bash # Create test directory mkdir -p /tmp/ansible-test cp playbook.yml /tmp/ansible-test/
# Run syntax check in isolation cd /tmp/ansible-test ansible-playbook --syntax-check playbook.yml ```
Related Issues
- [ansible-playbook-undefined-variable-jinja2-strict-mode](/articles/ansible-playbook-undefined-variable-jinja2-strict-mode)
- [ansible-jinja2-template-errors](/articles/ansible-jinja2-template-errors)
- [ansible-yaml-best-practices](/articles/ansible-yaml-best-practices)
Related Articles
- [WordPress troubleshooting: Ansible Artifact Download Uses an Old Mi](ansible-artifact-download-uses-an-old-mirror-after-proxy-change)
- [WordPress troubleshooting: Ansible Audit Trail Misses Events Under ](ansible-audit-trail-misses-events-under-burst-load)
- [WordPress troubleshooting: Ansible Background Worker Gets Stuck in ](ansible-background-worker-stuck-in-a-retry-loop)
- [WordPress troubleshooting: Ansible Backup Completes but Restore Fai](ansible-backup-completes-but-restore-fails-checksum-validation)
- [WordPress troubleshooting: Ansible Batch Importer Duplicates Rows A](ansible-batch-importer-duplicates-rows-after-a-retry)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "WordPress troubleshooting: Ansible Playbook Syntax Error - YAML Par", "description": "Learn how to fix Ansible Playbook Syntax Error - YAML Parsing Failed. Professional WordPress troubleshooting solutions with step-by-step guidance. WP error fix, WordPress optimization, WP security, WordPress performance.", "url": "https://www.fixwikihub.com/ansible-playbook-syntax-yaml-error", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-12-15T19:14:01.783Z", "dateModified": "2025-12-15T19:14:01.783Z" } </script>