Why Ansible Playbooks Fail
Ansible is the industry-standard tool for infrastructure automation and configuration management. It’s agentless (uses SSH), uses simple YAML syntax, and is incredibly powerful—but playbook failures can be cryptic and frustrating, especially when managing dozens or hundreds of servers.
This guide covers the most common failure scenarios and how to systematically debug them.
Prerequisites
- Ansible 2.14+ installed on your control node.
- SSH key-based authentication configured to target hosts.
- A working inventory file (
/etc/ansible/hostsor a custom.ini/.ymlfile).
Common Errors and Solutions
1. SSH Connection Failures
Error: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh"}
This is the most fundamental error. Ansible communicates entirely over SSH.
Debugging Steps:
- Test manually:
ssh -i ~/.ssh/your_key user@target_ip - Check inventory: Ensure
ansible_host,ansible_user, andansible_ssh_private_key_fileare correct. - Firewall: Verify port 22 is open on the target (
sudo ufw statusoriptables -L). - Bastion/Jump Host: If the target is behind a bastion, configure ProxyJump:
[webservers] internal-web ansible_host=10.0.0.5 ansible_ssh_common_args='-o ProxyJump=bastion_user@bastion_ip'
2. Privilege Escalation (become) Failures
Error: fatal: [host]: FAILED! => {"msg": "Missing sudo password"}
Ansible needs become: yes to run tasks as root, but the remote user may require a sudo password.
Solutions:
- Option A: Configure passwordless sudo for the Ansible user on the remote host:
# On the remote host, add to /etc/sudoers (via visudo): ansible_user ALL=(ALL) NOPASSWD:ALL - Option B: Pass the sudo password at runtime:
ansible-playbook site.yml --ask-become-pass - Option C: Store it encrypted in Ansible Vault:
ansible-vault encrypt_string 'MyS3cretPa$$' --name 'ansible_become_password'
3. Undefined Variable Errors
Error: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'my_var' is undefined"}
Variables in Ansible have a complex precedence hierarchy (inventory, group_vars, host_vars, role defaults, play vars, extra vars, etc.).
Debugging Steps:
- Print all vars for a host:
ansible target_host -m debug -a "var=hostvars[inventory_hostname]" - Add a debug task before the failure:
- name: Debug my_var debug: var: my_var - Check variable scope: If the variable is defined in a role’s
defaults/main.yml, it can be overridden by almost anything. If it’s invars/main.yml, it has higher precedence. - Provide a default: Use
{{ my_var | default('fallback_value') }}to prevent failures on optional variables.
4. Idempotency Issues (Task Fails on Re-run)
Problem: The playbook works the first time but fails on the second run because it tries to create something that already exists.
Root Cause: Using command or shell modules instead of purpose-built modules.
Bad (Not Idempotent):
- name: Create app directory
command: mkdir /opt/myapp
Good (Idempotent):
- name: Create app directory
file:
path: /opt/myapp
state: directory
owner: appuser
mode: '0755'
If you must use command/shell, add conditions:
- name: Initialize database (only if not already done)
command: /opt/myapp/init_db.sh
args:
creates: /opt/myapp/.db_initialized
5. Module Not Found / Collection Missing
Error: ERROR! couldn't resolve module/action 'community.general.ufw'
In Ansible 2.10+, many modules were moved into separate Collections.
Fix:
ansible-galaxy collection install community.general
Add a requirements.yml to your project root so others can install dependencies:
# requirements.yml
collections:
- name: community.general
- name: ansible.posix
Install with: ansible-galaxy install -r requirements.yml
Summary
| Error | First Thing to Check |
|---|---|
| SSH Connection Failed | Test ssh manually to the target |
| Missing sudo password | Configure passwordless sudo or --ask-become-pass |
| Undefined variable | Add debug: var=my_var task; check precedence |
| Task fails on re-run | Replace command/shell with built-in modules |
| Module not found | Install the required Collection via ansible-galaxy |