The Ansible Debugger
block/rescue, from earlier in this course, handles failure programmatically — recovery logic decided and written in advance, before anything actually goes wrong. The Ansible debugger is different in kind: it’s for the moment you don’t yet know what’s wrong, and need to actually look around before deciding what to do next.
What The Debugger Actually Is?
An interactive prompt Ansible drops you into, right at the exact moment a trigger condition is met — a task failing, most commonly — letting you inspect variables, the failed task’s actual arguments, and even retry the task after making a fix, all without stopping the playbook, editing files, and starting over from scratch.
Enabling It With debugger:
- name: Deploy config
ansible.builtin.template:
src: app.conf.j2
dest: /etc/myapp/app.conf
debugger: on_failedThis means: if this specific task fails, drop into the interactive debugger right there, at that exact point.
The Trigger Conditions: on_failed, on_unreachable, on_skipped, always
on_failed— the task genuinely fails.on_unreachable— the host becomes unreachable during this task, such as a lost SSH connection.on_skipped— the task is skipped, most commonly by its ownwhen:condition. Genuinely useful for confirming why something was skipped when you didn’t expect it to be.always— drops into the debugger every single time this task runs, regardless of outcome. Useful for deliberate, focused investigation of one specific task — not something to leave on permanently, since it pauses execution unconditionally, every run.
What Happens When It Fires
Normal execution pauses at that exact point. Instead of the task failing and the play halting on an unhandled error, you’re dropped into an interactive prompt with full access to that task’s context — the current host’s variables and facts, the task’s own arguments, whatever’s been registered so far — exactly like pausing a debugger mid-execution in a traditional programming language.
A First Look At The (debug) Prompt
[ubuntu] TASK: Deploy config (debug)>The prompt itself shows which host and task you’re currently paused at. From here, you type debugger commands — covered in full detail in the next chapter — but a quick preview:
[ubuntu] TASK: Deploy config (debug)> p app_port
8080p prints a variable’s current value; redo retries the task; continue proceeds normally; quit aborts the run entirely.
Setting It At The Block Or Play Level
debugger: can also be set on an entire block — applying to every task within it individually, the same propagation behavior established for other block-level keywords in the blocks and handlers section — or on the whole play:
- name: My Play
hosts: servers
debugger: on_failed
tasks:
- name: Task one
ansible.builtin.debug:
msg: "..."
- name: Task two
ansible.builtin.debug:
msg: "..."Now every task in this play triggers the debugger on failure, not just one specifically marked task — useful when troubleshooting a whole play you haven’t yet narrowed down to a specific problem task.
A Realistic Example
- name: Deploy config from template
ansible.builtin.template:
src: app.conf.j2
dest: /etc/myapp/app.conf
debugger: on_failedIf app.conf.j2 references an undefined variable and this task fails, instead of the play halting with a generic error, you’re dropped directly into the debug prompt — with full access to inspect exactly what variables are and aren’t defined at that point, decide on a fix, and potentially retry without restarting the whole playbook at all.
Best Practices
- Use
debugger: on_failedon specific tasks you suspect might fail and want to investigate interactively, rather than leaving it on everything permanently. - Use
on_skippedspecifically when awhen:condition isn’t behaving as expected, to confirm exactly why. - Avoid
alwaysexcept for deliberate, temporary investigation of one specific task — remove it once you’re done, since it pauses execution on every single run otherwise. - Set
debugger:at the play level when troubleshooting broadly, and narrow it down to a specific task once you’ve actually identified where the problem lives.