Introduction

When Ansible fails, the error message usually tells you exactly what's wrong — if you know where to look. This guide covers the most common errors, what causes them, and how to fix them.

Debugging Techniques

Verbose Mode

# Increasing verbosity
ansible-playbook site.yml -v      # Basic
ansible-playbook site.yml -vv     # More detail
ansible-playbook site.yml -vvv    # SSH debugging
ansible-playbook site.yml -vvvv   # Maximum (connection debug)

Debug Module

- name: Print variable
  ansible.builtin.debug:
    var: my_variable

- name: Print message
  ansible.builtin.debug:
    msg: "Host {{ inventory_hostname }}, IP {{ ansible_host }}"

- name: Print all variables
  ansible.builtin.debug:
    var: hostvars[inventory_hostname]

Check Mode (Dry Run)

# Show what would change without changing
ansible-playbook site.yml --check --diff

Step Mode

# Confirm each task before running
ansible-playbook site.yml --step

Start at Specific Task

ansible-playbook site.yml --start-at-task="Deploy application"

SSH Connection Errors

"UNREACHABLE! => SSH Error"

fatal: [web-01]: UNREACHABLE! => {"msg": "Failed to connect to the host via ssh"}

Fixes:

# Test SSH manually
ssh -vvv deploy@web-01

# Check host is reachable
ping web-01

# Check SSH key
ssh-add -l

# Specify key
ansible-playbook site.yml --private-key=~/.ssh/mykey

# Disable host key checking (dev only)
ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook site.yml

"Permission denied (publickey)"

# Copy SSH key to remote host
ssh-copy-id deploy@web-01

# Or specify password
ansible-playbook site.yml --ask-pass

# Check key permissions
chmod 600 ~/.ssh/id_rsa
chmod 700 ~/.ssh

Connection Timeout

# ansible.cfg — increase timeout
[defaults]
timeout = 30

[ssh_connection]
ssh_args = -C -o ConnectTimeout=30

Permission Errors

"MODULE FAILURE: Permission denied"

# WRONG — needs root
- name: Install package
  ansible.builtin.apt:
    name: nginx

# RIGHT — add become
- name: Install package
  ansible.builtin.apt:
    name: nginx
  become: true

"sudo: a password is required"

# Provide sudo password
ansible-playbook site.yml --ask-become-pass

# Or configure passwordless sudo on remote host
echo "deploy ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/deploy

Variable Errors

"undefined variable"

fatal: [web-01]: FAILED! => {"msg": "'my_var' is undefined"}

Fixes:

# Use default filter
value: "{{ my_var | default('fallback') }}"

# Check if defined
- name: Task
  ...
  when: my_var is defined

# Define in the right place
# group_vars/all.yml, host_vars/hostname.yml, or playbook vars

"dict object has no attribute"

# WRONG — attribute doesn't exist
msg: "{{ result.stdout }}"

# DEBUG — see what's actually in the variable
- debug: var=result

# RIGHT — use default
msg: "{{ result.stdout | default('') }}"

Module Errors

"No module named..."

# Install required collection
ansible-galaxy collection install community.general

# Check if module exists
ansible-doc -l | grep module_name

"Unsupported parameters"

fatal: [web-01]: FAILED! => {"msg": "Unsupported parameters for (apt) module: name_"}

Check for typos in parameter names:

# WRONG
- apt:
    name_: nginx    # Typo!

# RIGHT
- apt:
    name: nginx

"Could not find or access"

# File not found — check paths
- copy:
    src: myfile.conf    # Relative to files/ or playbook dir
    dest: /etc/myapp/

# Check: does files/myfile.conf exist?
# Or use absolute path:
    src: /path/to/myfile.conf

YAML Syntax Errors

"could not find expected ':'"

# WRONG — colon in value without quotes
- debug:
    msg: Error: something failed

# RIGHT — quote strings with colons
- debug:
    msg: "Error: something failed"

"found character that cannot start any token"

# WRONG — tab indentation
- name: Task
	ansible.builtin.debug:    # TAB character!

# RIGHT — use spaces (2 or 4)
- name: Task
  ansible.builtin.debug:

Indentation Errors

# WRONG
- name: Task
  ansible.builtin.apt:
  name: nginx        # Wrong indent — looks like new task

# RIGHT
- name: Task
  ansible.builtin.apt:
    name: nginx      # Indented under module

Slow Playbook Performance

# ansible.cfg — performance settings
[defaults]
forks = 20                    # Parallel hosts (default: 5)
gathering = smart             # Cache facts
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible-facts

[ssh_connection]
pipelining = True             # Major speed boost
ssh_args = -C -o ControlMaster=auto -o ControlPersist=600s
# Skip fact gathering if not needed
- hosts: all
  gather_facts: false

# Combine package installs
- apt:
    name: [nginx, redis, git, curl]
    state: present

Common Error Reference

ErrorCauseFix
UNREACHABLESSH can't connectCheck SSH, firewall, hostname
Permission deniedNo sudo / wrong userAdd become: true, check SSH key
Undefined variableVariable not setUse default() filter, define in vars
No module namedCollection not installedansible-galaxy collection install
Unsupported parametersTypo in parameterCheck ansible-doc module_name
could not find ':'YAML syntax (unquoted colon)Quote strings with special chars
TimeoutSlow network / commandIncrease timeout, use async
Idempotency failureUsing command instead of moduleSwitch to proper module

Useful Debug Commands

# Test connectivity
ansible all -m ping

# Run ad-hoc command
ansible web-01 -m command -a "uptime"

# List all hosts in inventory
ansible-inventory --list

# Show host variables
ansible-inventory --host web-01

# Check module documentation
ansible-doc apt
ansible-doc -s apt    # Short snippet

# Syntax check (no execution)
ansible-playbook site.yml --syntax-check

# List tasks
ansible-playbook site.yml --list-tasks

# List hosts
ansible-playbook site.yml --list-hosts

Conclusion

Most Ansible errors fall into 5 categories: SSH connection, permissions, undefined variables, module issues, and YAML syntax. Use -vvv for detailed output. Use debug to inspect variables. Use --check --diff to preview changes. The error message almost always tells you the exact problem — read it carefully. For persistent issues, check ansible-doc for the correct module parameters and ansible-inventory to verify your host configuration.