Skip to content

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_failed

This 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 own when: 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
8080

p 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_failed

If 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_failed on specific tasks you suspect might fail and want to investigate interactively, rather than leaving it on everything permanently.
  • Use on_skipped specifically when a when: condition isn’t behaving as expected, to confirm exactly why.
  • Avoid always except 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.
Last updated on