Common Ansible Errors and Solutions
Overview
This document provides solutions to common Ansible errors, including syntax errors, module errors, connection issues, and runtime problems.
Syntax Errors
Error: mapping values are not allowed here
ERROR! Syntax Error while loading YAML.
mapping values are not allowed hereCause: YAML indentation error or missing quote
Example Problem:
- name: Configure app
template:
src: config.j2
dest: /etc/app/config.yml
vars:
db_host: localhost:5432 # WRONG: colon not quotedSolution:
- name: Configure app
template:
src: config.j2
dest: /etc/app/config.yml
vars:
db_host: "localhost:5432" # QuotedError: found undefined alias
ERROR! Syntax Error while loading YAML.
found undefined alias 'anchor'Cause: Using YAML anchor/alias incorrectly
Solution: Ensure anchors are defined before use
# Define anchor
common_packages: &common_packages
- git
- curl
- vim
# Use alias
- name: Install common packages
apt:
name: *common_packagesError: could not find expected ':'
ERROR! could not find expected ':'Cause: Missing colon or improper YAML structure
Example Problem:
- name Install package # Missing colon after name
apt:
name nginx # Missing colon after nameSolution:
- name: Install package
apt:
name: nginxModule Errors
Error: Unsupported parameters for module
ERROR! Unsupported parameters for (module) module: parameter_nameCause: Using wrong parameter name or typo
Example Problem:
- name: Create file
file:
path: /tmp/test
state: present
mod: '0644' # WRONG: should be 'mode'Solution:
- name: Create file
file:
path: /tmp/test
state: present
mode: '0644' # Correct parameter nameHow to check: Use ansible-doc module_name to see correct parameters
Error: MODULE FAILURE
fatal: [host]: FAILED! => {"changed": false, "module_stderr": "..."}Common Causes:
- Python not installed on target
- Wrong Python interpreter
- SELinux blocking module execution
Solutions:
# Specify Python interpreter in inventory
[webservers]
server1 ansible_python_interpreter=/usr/bin/python3
# Or in playbook
- hosts: all
vars:
ansible_python_interpreter: /usr/bin/python3Error: Missing required arguments
fatal: [host]: FAILED! => {"changed": false, "msg": "missing required arguments: name"}Cause: Required module parameter not provided
Solution: Add the required parameter
# Wrong
- name: Install package
apt:
state: present
# Correct
- name: Install package
apt:
name: nginx
state: presentTemplate Errors
Error: template error while templating string
fatal: [host]: FAILED! => {"msg": "An unhandled exception occurred while templating..."}Common Causes:
- Undefined variable
- Wrong filter syntax
- Jinja2 syntax error
Example Problem:
- name: Configure app
template:
src: config.j2
dest: /etc/app/config.yml
vars:
port: "{{ app_port }}" # app_port undefinedSolutions:
# Use default filter
vars:
port: "{{ app_port | default(8080) }}"
# Or use required filter
vars:
port: "{{ app_port | required('app_port must be defined') }}"
# Or check if defined
- name: Configure app
template:
src: config.j2
dest: /etc/app/config.yml
when: app_port is definedError: Unexpected templating type error
fatal: [host]: FAILED! => {"msg": "Unexpected templating type error occurred on (...)"}Cause: Wrong variable type (e.g., trying to use int as string)
Solution: Use type conversion filters
# Convert to string
port: "{{ app_port | string }}"
# Convert to int
replicas: "{{ replica_count | int }}"
# Convert to bool
enabled: "{{ feature_enabled | bool }}"Connection Errors
Error: Failed to connect to the host via ssh
fatal: [host]: UNREACHABLE! => {"msg": "Failed to connect to the host via ssh"}Common Causes:
- Host not accessible
- Wrong SSH key
- Wrong username
- SSH not running on host
Solutions:
# Test SSH connectivity
ssh user@host
# Check Ansible can ping
ansible host -m ping
# Use correct SSH key
ansible-playbook -i inventory playbook.yml --private-key=~/.ssh/id_rsa
# Specify user in inventory
[webservers]
server1 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsaError: Permission denied (publickey)
fatal: [host]: UNREACHABLE! => {"msg": "Failed to connect to the host via ssh: Permission denied (publickey)."}Solutions:
# Ensure SSH key is added to target
ssh-copy-id user@host
# Or specify key in inventory
[webservers]
server1 ansible_ssh_private_key_file=~/.ssh/custom_key
# Check SSH agent
ssh-add -l
ssh-add ~/.ssh/id_rsaError: Authentication or permission failure
fatal: [host]: UNREACHABLE! => {"msg": "Authentication or permission failure."}Solutions:
# Use password authentication (less secure)
- hosts: all
vars:
ansible_ssh_pass: password # Better to use vault
ansible_become_pass: password
# Or use ask-pass
ansible-playbook -i inventory playbook.yml --ask-pass --ask-become-passPrivilege Escalation Errors
Error: Missing sudo password
fatal: [host]: FAILED! => {"msg": "Missing sudo password"}Solutions:
# Provide sudo password at runtime
ansible-playbook -i inventory playbook.yml --ask-become-pass
# Or configure passwordless sudo on target
# /etc/sudoers.d/ansible
ansible_user ALL=(ALL) NOPASSWD: ALLError: you must be root
fatal: [host]: FAILED! => {"msg": "Could not create file: Permission denied"}Solution: Add become: yes to task or play
- name: Install package
apt:
name: nginx
state: present
become: yes
# Or for entire play
- hosts: all
become: yes
tasks:
- name: Install package
apt:
name: nginxVariable Errors
Error: The task includes an option with an undefined variable
fatal: [host]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'variable' is undefined"}Solutions:
# Use default filter
- name: Use variable with default
debug:
msg: "{{ my_var | default('default_value') }}"
# Check if defined before use
- name: Use variable conditionally
debug:
msg: "{{ my_var }}"
when: my_var is defined
# Use required filter to make it explicit
- name: Require variable
debug:
msg: "{{ my_var | required('my_var must be defined') }}"Error: Conflicting variable name
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see detailsCause: Variable or group name contains invalid characters (hyphens, spaces)
Solution: Use underscores instead
# Wrong
[web-servers]
# Correct
[web_servers]Inventory Errors
Error: Could not match supplied host pattern
[WARNING]: Could not match supplied host pattern, ignoring: webserversCause: Host group not defined in inventory
Solution: Check inventory file
# inventory/hosts
[webservers]
web1.example.com
web2.example.com
[databases]
db1.example.comError: Unable to parse inventory
[WARNING]: Unable to parse /path/to/inventory as an inventory sourceCause: Invalid inventory format
Solution: Fix inventory syntax
# Wrong - mixing styles
[webservers]
web1 ansible_host=192.168.1.10
web2
ansible_host: 192.168.1.11 # YAML syntax in INI file
# Correct - consistent INI format
[webservers]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11Loop Errors
Error: Invalid data passed to 'loop'
fatal: [host]: FAILED! => {"msg": "Invalid data passed to 'loop', it requires a list"}Cause: Loop variable is not a list
Solution: Ensure loop variable is a list
# Wrong
- name: Install packages
apt:
name: "{{ item }}"
loop: nginx # String, not list
# Correct
- name: Install packages
apt:
name: "{{ item }}"
loop:
- nginx
- python3Error: with_items is deprecated
[DEPRECATION WARNING]: with_items is deprecated, use loop insteadSolution: Replace with_items with loop
# Old style (deprecated)
- name: Install packages
apt:
name: "{{ item }}"
with_items:
- nginx
- python3
# New style
- name: Install packages
apt:
name: "{{ item }}"
loop:
- nginx
- python3Handler Errors
Error: Handler not found
ERROR! The requested handler 'restart nginx' was not foundCause: Handler name mismatch or handler not defined
Solution: Ensure handler name matches exactly
# tasks/main.yml
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx # Must match handler name exactly
# handlers/main.yml
- name: restart nginx # Must match notification exactly
systemd:
name: nginx
state: restartedInclude/Import Errors
Error: Unable to retrieve file contents
fatal: [host]: FAILED! => {"msg": "Unable to retrieve file contents. Could not find or access 'file.yml'"}Cause: File path incorrect or file doesn't exist
Solution: Check file path (relative to playbook location)
# Wrong
- include_tasks: tasks/install.yml # If tasks/ doesn't exist
# Correct
- include_tasks: install.yml # File in same directory
# Or
- include_tasks: roles/common/tasks/install.yml # Full pathError: Include/Import loop detected
ERROR! Recursively included/imported file is causing infinite loopCause: Circular dependency (file A includes file B, file B includes file A)
Solution: Restructure includes to avoid circular dependencies
Collection Errors
Error: couldn't resolve module/action
ERROR! couldn't resolve module/action 'community.general.docker_container'Cause: Collection not installed
Solution: Install required collection
# Install single collection
ansible-galaxy collection install community.general
# Install from requirements.yml
# requirements.yml
collections:
- name: community.general
version: ">=5.0.0"
ansible-galaxy collection install -r requirements.ymlError: Collection version conflict
ERROR! Requirement already satisfied by a different versionSolution: Update or downgrade collection
# Force reinstall
ansible-galaxy collection install community.general --force
# Install specific version
ansible-galaxy collection install community.general:5.0.0Dry-Run / Check Mode Errors
Error: This module does not support check mode
fatal: [host]: FAILED! => {"msg": "This module does not support check mode"}Cause: Module doesn't support check mode
Solution: Skip check mode for this task
- name: Command that doesn't support check mode
command: /usr/local/bin/custom-script.sh
check_mode: no # Always run, even in check modeDebugging Tips
Enable Verbose Output
# Basic verbosity
ansible-playbook playbook.yml -v
# More details
ansible-playbook playbook.yml -vv
# Very verbose (shows module arguments)
ansible-playbook playbook.yml -vvv
# Connection debugging
ansible-playbook playbook.yml -vvvvUse Debug Module
# Print variable
- name: Debug variable
debug:
var: my_variable
# Print message
- name: Debug message
debug:
msg: "Value is {{ my_variable }}"
# Print all facts
- name: Print all facts
debug:
var: ansible_facts
# Conditional debug
- name: Debug when condition met
debug:
msg: "Debug message"
when: ansible_distribution == "Ubuntu"Use assert Module
# Validate conditions
- name: Assert variables are defined
assert:
that:
- app_version is defined
- app_version | length > 0
- app_port | int > 0
- app_port | int < 65536
fail_msg: "Invalid configuration"
success_msg: "Configuration validated"Performance Issues
Slow Playbook Execution
Solutions:
- Enable SSH pipelining
# ansible.cfg
[ssh_connection]
pipelining = True- Use fact caching
# ansible.cfg
[defaults]
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400- Disable fact gathering if not needed
- hosts: all
gather_facts: no- Use async for long tasks
- name: Long running task
command: /usr/bin/long-task
async: 3600
poll: 0High Memory Usage
Solutions:
- Process hosts in batches
- hosts: all
serial: 10 # Process 10 hosts at a time- Use free strategy
- hosts: all
strategy: free # Don't wait for all hosts to complete taskError Prevention Checklist
- Run yamllint before ansible-playbook
- Run ansible-lint on all playbooks
- Use --syntax-check before execution
- Test with --check mode first
- Start with limited host scope (--limit)
- Use tags for incremental testing
- Enable verbose mode for debugging (-vvv)
- Validate variables with assert
- Use molecule for role testing
- Test in staging before production
- Keep collections up to date
- Document custom variables
- Use version control for all playbooks
Quick Reference Commands
# Syntax check
ansible-playbook playbook.yml --syntax-check
# Dry run
ansible-playbook playbook.yml --check --diff
# Run with tags
ansible-playbook playbook.yml --tags webserver
# Limit to specific hosts
ansible-playbook playbook.yml --limit webserver1
# Verbose output
ansible-playbook playbook.yml -vvv
# List tasks
ansible-playbook playbook.yml --list-tasks
# List hosts
ansible-playbook playbook.yml --list-hosts
# Step through tasks
ansible-playbook playbook.yml --step
# Start at specific task
ansible-playbook playbook.yml --start-at-task="Install nginx"