Ansible Playbook Error Handling

Ansible Playbook Error Handling

When an Ansible task returns a non-zero status code, the task execution fails and prints an error message.

Ignore Errors

<span>ignore_errors: true</span> can be used to ignore errors and continue execution.

- name: Do not count this as a failure
  ansible.builtin.command: /bin/false
  ignore_errors: true

<span>ignore_errors: true</span> can be set at the Playbook level.

Ignore Unreachable Host Errors

When a host is unreachable for some reason (e.g., the node is temporarily rebooting), the task will fail. The <span>ignore_unreachable: true</span> option can be used to ignore this error, allowing subsequent tasks to continue executing on that node.

- name: This executes, fails, and the failure is ignored
  ansible.builtin.command: /bin/true
  ignore_unreachable: true

- name: This executes, fails, and ends the play for this host
  ansible.builtin.command: /bin/true

<span>ignore_unreachable: true</span> can be set at the Playbook level.

Reset Host Status

When a host is unreachable, it will be marked as <span>UNREACHABLE</span>. The <span>meta: clear_host_errors</span> command can be used to reset the host status.

- name: This executes, fails, and the failure is ignored
  ansible.builtin.command: /bin/true

- name: clear host errors
  ansible.builtin.meta: clear_host_errors

- name: This executes, fails, and ends the play for this host
  ansible.builtin.command: /bin/true

Force Execute Handlers

When a host has a task that fails, it will be removed from the queue. If the host has <span>handlers</span> tasks, these <span>handlers</span> will not be executed. The <span>force_handlers: True</span> option can be used to force the execution of <span>handlers</span>.

In addition to <span>force_handlers: True</span>, you can set <span>force_handlers = True</span> in <span>ansible.cfg</span> or add <span>--force-handlers</span> in Ad-Hoc commands.

Define Task Status

failed_when Defines Task Failure Conditions

The <span>failed_when</span> option can be used to set task failure conditions. Here is an example:

- name: set when status is failed
  ansible.builtin.command: ls /tmp/testdir
  register: command_result
  failed_when: &gt;
    (command_result.rc == 0) or
    ( 'No such' not in command_result.stderr)
- name: print var command_result
  ansible.builtin.debug:
    var: command_result

This is a demonstration example, indicating that if the <span>/tmp/testdir</span> directory exists, the task fails.

<span>failed_when</span> supports lists (the list acts like <span>and</span>).

failed_when:
    - result.rc == 0
    - '"No such" not in result.stderr'

You can check the contents of <span>command_result</span> to set the judgment conditions. The <span>command_result.rc</span> represents the status code, and the <span>command_result.stderr</span> represents the error output.

changed_when Defines Task Change Conditions

<span>changed_when</span> can be used to set the conditions under which a task is considered <span>changed</span>. The <span>changed_when: false</span> option indicates that the status is always <span>ok</span>.

- name: set status when is changed
  ansible.builtin.command: ls /tmp/testdir
  register: command_result
  changed_when: &gt;
    (command_result.rc != 0) or
    ( 'No such' in command_result.stderr)
  failed_when: command_result.rc == 0
- name: set status always ok
  ansible.builtin.command: id
  changed_when: false

<span>changed_when</span> also supports lists (<span>and</span>).

<span>changed_when</span> supports variables:

vars:
  log_dir: /tmp/testdir
tasks:
- name: set status when is changed
  ansible.builtin.shell: mkdir {{ log_dir }} || true
  register: command_result
  changed_when:
  - 'command_result.stderr != "mkdir: cannot create directory ‘" ~ log_dir ~ "’: File exists"'

<span>changed_when</span> uses variable formatting as <span>" ~ log_dir ~ "</span>.

Ensure Command and Shell Modules Succeed

Directly using the example from the official website:

tasks:
  - name: Run this command and ignore the result
    ansible.builtin.shell: /usr/bin/somecommand || /bin/true

Define Playbook Stop Conditions

any_errors_fatal

<span>any_errors_fatal</span> can be set to stop all tasks in the Playbook if any task execution fails.

For example, in a cluster scenario, all nodes must successfully initialize their configurations before proceeding with cluster configuration.

- name: test any errors fatal
  hosts: all
  become: true
  gather_facts: false
  any_errors_fatal: true
  tasks:
  - name: test any error fatal
    ansible.builtin.shell: ls /tmp/testdir
  - name: debug
    ansible.builtin.debug:
      msg: "Hello World!"
    changed_when: false

<span>any_errors_fatal</span> can be used in Playbooks, individual Plays, or blocks.

When used in a block, if the failed host is successfully rescued by a task in the rescue section, subsequent tasks will continue on the failed host.

[root@study ansible]# cat test.yml
- name: test any errors fatal
  hosts: all
  become: true
  gather_facts: false
  tasks:
  - name: test any error fatal
    block:
    - name: ls /tmp/testdir
      ansible.builtin.shell: ls /tmp/testdir
    any_errors_fatal: true
    rescue:
    - name: rescue fail hosts
      ansible.builtin.debug:
        msg: "fix success!"
  - name: debug
    ansible.builtin.debug:
      msg: "Hello World!"
    changed_when: false
[root@study ansible]# ansible-playbook test.yml

PLAY [test any errors fatal] **************************************************************************************************************************************

TASK [ls /tmp/testdir] ********************************************************************************************************************************************
fatal: [serverb]: FAILED! =&gt; {"changed": true, "cmd": "ls /tmp/testdir", "delta": "0:00:00.005889", "end": "2025-06-23 17:00:53.031011", "msg": "non-zero return code", "rc": 2, "start": "2025-06-23 17:00:53.025122", "stderr": "ls: cannot access '/tmp/testdir': No such file or directory", "stderr_lines": ["ls: cannot access '/tmp/testdir': No such file or directory"], "stdout": "", "stdout_lines": []}
changed: [servera]

TASK [rescue fail hosts] ******************************************************************************************************************************************
ok: [serverb] =&gt; {
    "msg": "fix success!"
}

TASK [debug] ******************************************************************************************************************************************************
ok: [servera] =&gt; {
    "msg": "Hello World!"
}
ok: [serverb] =&gt; {
    "msg": "Hello World!"
}

PLAY RECAP ********************************************************************************************************************************************************
servera                    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverb                    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=1    ignored=0

Set Maximum Percentage of Failed Hosts

<span>max_fail_percentage</span> can be set to determine how many host tasks can fail in a batch before stopping the Playbook.

---
- hosts: webservers
  max_fail_percentage: 30
  serial: 10

This indicates that for every batch of 10 hosts, if more than 3 hosts (not including 3) fail (30%), the entire Playbook will stop.

It is emphasized that the <span>max_fail_percentage</span> will only trigger if the percentage of failed hosts exceeds the set value. According to the example above, the Playbook will only stop if 4 hosts fail in each batch.

Leave a Comment