| name | debug |
| description | Use when playbooks fail with UNREACHABLE, permission denied, MODULE FAILURE, or undefined variable errors. Use when SSH connections fail or sudo password is missing. |
Ansible Debugging
Ansible errors fall into four categories: connection, authentication, module, and syntax. Systematic diagnosis starts with identifying the category, then isolating the specific cause.
Identify the error category from the failure message:
- **Connection**: UNREACHABLE, network timeout
- **Authentication**: Permission denied, missing sudo password
- **Module**: MODULE FAILURE, invalid parameters
- **Syntax**: YAML parse error, indentation issues
For **Connection Errors**:
- Test SSH directly: `ssh -v -i /path/to/key user@hostname`
- Check port connectivity: `nc -zv hostname 22`
- Verify inventory parsing: `ansible-inventory --host hostname`
- Common causes: wrong IP/hostname, firewall blocking port 22, SSH key permissions (must be 600)
For **Authentication Errors**:
- Test with explicit options: `ansible hostname -m ping -u user --private-key /path/to/key`
- For sudo password issues: use `ansible-playbook playbook.yml --ask-become-pass`
- Or configure NOPASSWD in `/etc/sudoers`
- Verify SSH key permissions are 600
For **Module Errors**:
- Check module documentation: `ansible-doc ansible.builtin.copy`
- Verify module parameters match your Ansible version: `ansible --version`
- Ensure required parameters are provided
- Check target system state matches module expectations
For **Variable Errors**:
- Use default filter for optional variables: `{{ my_var | default('fallback') }}`
- Debug variable values: Add `ansible.builtin.debug` task with `var: problematic_variable`
- Check variable precedence (role defaults < inventory < playbook < extra vars)
Use progressive verbosity for deeper diagnosis:
- `-v`: Task results
- `-vv`: Task input parameters
- `-vvv`: SSH connection details
- `-vvvv`: Full plugin internals
Start with -v and increase only if needed.
Isolate the problem:
- Run syntax check: `ansible-playbook --syntax-check playbook.yml`
- Dry run: `ansible-playbook --check playbook.yml`
- Step through tasks: `ansible-playbook --step playbook.yml`
- Start at specific task: `ansible-playbook --start-at-task "Task Name" playbook.yml`
- Limit to specific host: `ansible-playbook --limit hostname playbook.yml`
For performance issues:
- Enable task timing in `ansible.cfg`: `callback_whitelist = profile_tasks`
- Enable SSH pipelining: `pipelining = True` in `[ssh_connection]`
- Skip fact gathering if not needed: `gather_facts: no`
Quick Diagnosis
Connection Errors
ssh -v -i /path/to/key user@hostname
nc -zv hostname 22
ansible-inventory --host hostname
Common causes:
- Wrong IP/hostname in inventory
- Firewall blocking port 22
- SSH key permissions (must be 600)
Authentication Errors
ansible hostname -m ping -u user --private-key /path/to/key
ansible-playbook playbook.yml --ask-become-pass
Module Errors
ansible-doc ansible.builtin.copy
ansible --version
Variable Errors
{{ my_var | default('fallback') }}
- ansible.builtin.debug:
var: problematic_variable
Verbosity Levels
| Flag | Shows |
|---|
-v | Task results |
-vv | Task input parameters |
-vvv | SSH connection details |
-vvvv | Full plugin internals |
Start with -v, increase only if needed.
Debugging Commands
ansible-playbook --syntax-check playbook.yml
ansible-playbook --check playbook.yml
ansible-playbook --step playbook.yml
ansible-playbook --start-at-task "Task Name" playbook.yml
ansible-playbook --limit hostname playbook.yml
Common Error Patterns
| Error | Cause | Fix |
|---|
Permission denied (publickey) | SSH key not accepted | Check key permissions, verify authorized_keys |
Missing sudo password | become=true without password | Use --ask-become-pass or configure NOPASSWD |
No such file or directory | Path doesn't exist | Create parent directories first |
Unable to lock (apt/yum) | Package manager locked | Wait for other process, remove stale lock |
undefined variable | Variable not defined | Check spelling, use default() filter |
Performance Debugging
[defaults]
callback_whitelist = profile_tasks
[ssh_connection]
pipelining = True
- hosts: all
gather_facts: no