# Simplify error and rescue output

**URL:** <https://forum.ansible.com/t/simplify-error-and-rescue-output/45579>\
**Category:** Get Help\
**Tags:** ansible-core\
**Created:** [March 23, 2026, 1:37pm UTC](https://forum.ansible.com/t/simplify-error-and-rescue-output/45579 "2026-03-23T13:37:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![etfz](https://avatars.discourse-cdn.com/v4/letter/e/e95f7d/32.png) [@etfz](https://forum.ansible.com/u/etfz)\
**Post date:** [March 23, 2026, 1:37pm UTC](https://forum.ansible.com/t/simplify-error-and-rescue-output/45579/1 "2026-03-23T13:37:49Z")

</div>

Hi,

I have a task for configuring, testing and restarting apache. It works as expected, but the output is rather verbose. I’ve included sample output for a malformed configuration.

For the error I would like to do something like outputting only the `stderr` field.

The restore and delete backup tasks seem to output the whole task result. I would like to either output nothing at all, or perhaps only the file name or something, though I’m not sure exactly what the output is.

Using ansible core 2.19.4.

```yaml
- name: Configure apache
  block:
    - name: Copy files
      ansible.builtin.copy:
        src: apache/{{ item }}
        dest: "/usr/local/etc/apache24/Includes/{{ item }}"
        backup: true
      with_items:
        - 'macro-redirect-https.conf'
      register: updated

    - name: "Test config"
      ansible.builtin.shell: 'apachectl -t'
      when: updated is changed
      notify:
        - Restart apache
  rescue:
    - name: Restore backup
      ansible.builtin.copy:
        remote_src: true
        src: "{{ item['backup_file'] }}"
        dest: "{{ item['dest'] }}"
      with_items: "{{ updated.results }}"
      when: updated is changed
  always:
    - name: Delete backup
      ansible.builtin.file:
        path: "{{ item['backup_file'] }}"
        state: absent
      with_items: "{{ updated.results }}"
      when: updated is changed

```

Problematic output:

```auto
TASK [freebsd : Test config] *************************************************************************************************************
[ERROR]: Task failed: Module failed: non-zero return code
Origin: /home/e/ansible_quickstart/roles/freebsd/tasks/apache.yaml:27:7

25 register: updated
26
27 - name: "Test config"
         ^ column 7

fatal: [web01]: FAILED! => {
    "changed": true,
    "cmd": "apachectl -t",
    "delta": "0:00:00.044928",
    "end": "2026-03-23 13:03:58.560124",
    "msg": "non-zero return code",
    "rc": 1,
    "start": "2026-03-23 13:03:58.515196",
    "stderr": "AH00526: Syntax error on line 2 of macro 'redirecthttps' (defined on line 1 of \"/usr/local/etc/apache24/Includes/macro-redirect-https.conf\") used on line 4 of \"/usr/local/etc/apache24/vhost.conf\":\nInvalid command 'RedirectMatch2', perhaps misspelled or defined by a module not included in the server configuration",
    "stderr_lines": [
        "AH00526: Syntax error on line 2 of macro 'redirecthttps' (defined on line 1 of \"/usr/local/etc/apache24/Includes/macro-redirect-https.conf\") used on line 4 of \"/usr/local/etc/apache24/vhost.conf\":",
        "Invalid command 'RedirectMatch2', perhaps misspelled or defined by a module not included in the server configuration"
    ],
    "stdout": "",
    "stdout_lines": []
}

TASK [freebsd : Restore backup] **********************************************************************************************************
changed: [web01] => (item={'diff': [{'before_header': '/usr/local/etc/apache24/Includes/macro-redirect-https.conf', 'before': '<Macro RedirectHTTPS $hostname>\n RedirectMatch permanent ^/((?!\\.well-known/acme-challenge/).*)$ https://$hostname/\n</Macro>\n<Macro RedirectHTTPS2 $hostname>\n RedirectMatch2 permanent ^/((?!\\.well-known/acme-challenge/).*)$ https://$hostname/\n</Macro>\n', 'after_header': '/home/e/ansible_quickstart/roles/freebsd/files/apache/macro-redirect-https.conf', 'after': '<Macro RedirectHTTPS $hostname>\n RedirectMatch permanent ^/((?!\\.well-known/acme-challenge/).*)$ https://$hostname/\n RedirectMatch2 permanent ^/((?!\\.well-known/acme-challenge/).*)$ https://$hostname/\n</Macro>\n'}], 'dest': '/usr/local/etc/apache24/Includes/macro-redirect-https.conf', 'src': '/home/e/.ansible/tmp/ansible-tmp-1774267431.6175117-1991-16980776241965/.source.conf', 'md5sum': '1e390764aa09d46e448c23ef01634fed', 'checksum': 'ea2418ad9d069e6fccea1e6e67e12ded165b94eb', 'changed': True, 'backup_file': '/usr/local/etc/apache24/Includes/macro-redirect-https.conf.81850.2026-03-23@13:03:58~', 'uid': 0, 'gid': 0, 'owner': 'root', 'group': 'wheel', 'mode': '0644', 'state': 'file', 'size': 216, 'invocation': {'module_args': {'backup': True, 'dest': '/usr/local/etc/apache24/Includes/macro-redirect-https.conf', 'src': '/home/e/.ansible/tmp/ansible-tmp-1774267431.6175117-1991-16980776241965/.source.conf', '_original_basename': 'macro-redirect-https.conf', 'follow': False, 'checksum': 'ea2418ad9d069e6fccea1e6e67e12ded165b94eb', 'force': True, 'remote_src': False, 'unsafe_writes': False, 'content': None, 'validate': None, 'directory_mode': None, 'local_follow': None, 'mode': None, 'owner': None, 'group': None, 'seuser': None, 'serole': None, 'selevel': None, 'setype': None, 'attributes': None}}, 'failed': False, 'item': 'macro-redirect-https.conf', 'ansible_loop_var': 'item'})

TASK [freebsd : Delete backup] ***********************************************************************************************************
--- before
+++ after
@@ -1,4 +1,4 @@
 {
     "path": "/usr/local/etc/apache24/Includes/macro-redirect-https.conf.81850.2026-03-23@13:03:58~",
- "state": "file"
+ "state": "absent"
 }

changed: [web01] => (item={'diff': [{'before_header': '/usr/local/etc/apache24/Includes/macro-redirect-https.conf', 'before': '<Macro RedirectHTTPS $hostname>\n RedirectMatch permanent ^/((?!\\.well-known/acme-challenge/).*)$ https://$hostname/\n</Macro>\n<Macro RedirectHTTPS2 $hostname>\n RedirectMatch2 permanent ^/((?!\\.well-known/acme-challenge/).*)$ https://$hostname/\n</Macro>\n', 'after_header': '/home/e/ansible_quickstart/roles/freebsd/files/apache/macro-redirect-https.conf', 'after': '<Macro RedirectHTTPS $hostname>\n RedirectMatch permanent ^/((?!\\.well-known/acme-challenge/).*)$ https://$hostname/\n RedirectMatch2 permanent ^/((?!\\.well-known/acme-challenge/).*)$ https://$hostname/\n</Macro>\n'}], 'dest': '/usr/local/etc/apache24/Includes/macro-redirect-https.conf', 'src': '/home/e/.ansible/tmp/ansible-tmp-1774267431.6175117-1991-16980776241965/.source.conf', 'md5sum': '1e390764aa09d46e448c23ef01634fed', 'checksum': 'ea2418ad9d069e6fccea1e6e67e12ded165b94eb', 'changed': True, 'backup_file': '/usr/local/etc/apache24/Includes/macro-redirect-https.conf.81850.2026-03-23@13:03:58~', 'uid': 0, 'gid': 0, 'owner': 'root', 'group': 'wheel', 'mode': '0644', 'state': 'file', 'size': 216, 'invocation': {'module_args': {'backup': True, 'dest': '/usr/local/etc/apache24/Includes/macro-redirect-https.conf', 'src': '/home/e/.ansible/tmp/ansible-tmp-1774267431.6175117-1991-16980776241965/.source.conf', '_original_basename': 'macro-redirect-https.conf', 'follow': False, 'checksum': 'ea2418ad9d069e6fccea1e6e67e12ded165b94eb', 'force': True, 'remote_src': False, 'unsafe_writes': False, 'content': None, 'validate': None, 'directory_mode': None, 'local_follow': None, 'mode': None, 'owner': None, 'group': None, 'seuser': None, 'serole': None, 'selevel': None, 'setype': None, 'attributes': None}}, 'failed': False, 'item': 'macro-redirect-https.conf', 'ansible_loop_var': 'item'})

```

---

<div class="post-metadata">

**Author:** ![vbotka](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/vbotka/32/359_2.png) [@vbotka](https://forum.ansible.com/u/vbotka)\
**Post date:** [March 24, 2026, 5:24am UTC](https://forum.ansible.com/t/simplify-error-and-rescue-output/45579/2 "2026-03-24T05:24:39Z")

</div>

> [@etfz](#):
>
> would like to either output nothing at all, or perhaps only the file name or something,

You can reduce the block to a single copy task by using the [validate](https://docs.ansible.com/projects/ansible/latest/collections/ansible/builtin/copy_module.html#parameter-validate) option.

---

<div class="post-metadata">

**Author:** ![etfz](https://avatars.discourse-cdn.com/v4/letter/e/e95f7d/32.png) [@etfz](https://forum.ansible.com/u/etfz)\
**Post date:** [March 24, 2026, 8:02am UTC](https://forum.ansible.com/t/simplify-error-and-rescue-output/45579/3 "2026-03-24T08:02:31Z")

</div>

Thanks, but that is not sufficient in this instance, as I’m only providing partial configuration, which won’t validate without first having loaded the rest of Apache’s configuration.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 24, 2026, 12:15pm UTC](https://forum.ansible.com/t/simplify-error-and-rescue-output/45579/4 "2026-03-24T12:15:09Z")

</div>

I think the problem is you want to use the job log as a report. You could include a task which creates a report with just the data you want (say, using a template). But the job log is just a job log.

I don’t think you’re going to get a satisfactory answer. Sorry.

---

<div class="post-metadata">

**Author:** ![etfz](https://avatars.discourse-cdn.com/v4/letter/e/e95f7d/32.png) [@etfz](https://forum.ansible.com/u/etfz)\
**Post date:** [March 24, 2026, 3:13pm UTC](https://forum.ansible.com/t/simplify-error-and-rescue-output/45579/5 "2026-03-24T15:13:25Z")

</div>

I’m not sure what job logs and reports refer to, exactly. There are callback plugins that control output in various ways, so I thought it might have been possible to accomplish something like this.

Nevertheless, I have made some progress. I realised that the rescue and delete tasks, of course, output the result of the original copy task. I was able to achieve perfect results by doing this:

```diff
  rescue:
    - name: Restore backup
      ansible.builtin.copy:
        remote_src: true
        src: "{{ item.backup_file }}"
        dest: "{{ item.dest }}"
      with_items: "{{ updated.results }}"
+ loop_control:
+ label: "{{ item.item }}"
      when: updated is changed

```

I was able to simplify error output a little bit by doing this:

```yaml
    - block:
        - name: "Test config"
          ansible.builtin.shell: 'apachectl -t'
          register: config_test
          failed_when: False

        - ansible.builtin.assert:
            that: config_test.rc == 0
            fail_msg: "{{ config_test.stderr }}"
          no_log: true
          notify:
            - Restart apache
      when: updated is changed

```

But it’s not a significant improvement compared to using YAML output.

```auto
[ERROR]: Task failed: Action failed: AH00526: Syntax error on line 2 of macro 'redirecthttps' (defined on line 1 of "/usr/local/etc/apache24/Includes/macro-redirect-https.conf") used on line 4 of "/usr/local/etc/apache24/vhost.conf":
Invalid command 'RedirectMatch2', perhaps misspelled or defined by a module not included in the server configuration
Origin: /home/e/ansible_quickstart/roles/freebsd/tasks/apache.yaml:35:11

33 # - Restart apache
34
35 - name: Print the gateway for each host when defined
             ^ column 11

fatal: [web01]: FAILED! =>
    censored: 'the output has been hidden due to the fact that ''no_log: true'' was specified
        for this result'
    changed: false

```

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 24, 2026, 5:33pm UTC](https://forum.ansible.com/t/simplify-error-and-rescue-output/45579/6 "2026-03-24T17:33:14Z")

</div>

> [@etfz](#):
>
> I’m not sure what job logs and reports refer to, exactly.

Sorry; I guess I was in “read-my-mind” mode when I wrote that.

The _job log_ is what’s printed to the screen or log file as Ansible runs. A _report_ is text you generate, typically from templates, separate from the job log, and that may contain selected registered data, introspective data about the job itself, or other data gathered from the systems you are managing.

There’s a popular anti-pattern where people try to turn the job log into a report with varying degrees of success and frustration. The fact that you can embed mini-reports in the job log through the `ansible.builtin.debug` module (which is indispensable and I’m not arguing against that at all) blurs the distinction between job logs and reports. That’s perhaps where people new to Ansible get the idea to continue trying to coerce the log into a report beyond a practical point.

There are lots of “knobs” that control behavior of callbacks to change what ends up in a job log beyond `-v` and `--diff`. As you found out, `loop_control.label` does pretty much what you were looking for, and I had forgotten about it completely when I replied earlier.

Glad you found a solution you can live with, and for the reminder about `loop_control.label`.

---

<div class="post-metadata">

**Author:** ![vbotka](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/vbotka/32/359_2.png) [@vbotka](https://forum.ansible.com/u/vbotka)\
**Post date:** [March 25, 2026, 3:34am UTC](https://forum.ansible.com/t/simplify-error-and-rescue-output/45579/7 "2026-03-25T03:34:21Z")

</div>

> [@etfz](#):
>
> won’t validate without first having loaded the rest of Apache’s configuration.

I see. As a hint, take a look at [jtyr.config\_encoder\_filters](https://galaxy.ansible.com/ui/standalone/roles/jtyr/config_encoder_filters/).

---

<div class="post-metadata">

**Author:** ![RianKellyIT](https://avatars.discourse-cdn.com/v4/letter/r/edb3f5/32.png) [@RianKellyIT](https://forum.ansible.com/u/RianKellyIT)\
**Post date:** [April 5, 2026, 3:16am UTC](https://forum.ansible.com/t/simplify-error-and-rescue-output/45579/8 "2026-04-05T03:16:04Z")

</div>

For showing only stderr on failure, the cleanest approach is to register the result and then use a debug task in the rescue block with just the field you want:

```yaml
- block:
    - name: Test Apache config
      command: apachectl configtest
      register: configtest_result
      changed_when: false
  rescue:
    - name: Show config error
      debug:
        msg: "{{ configtest_result.stderr }}"

    - name: Restore backup
      copy:
        src: /etc/httpd/conf/httpd.conf.bak
        dest: /etc/httpd/conf/httpd.conf
        remote_src: yes

```

For the restore and backup tasks that show too much output, add `no_log: true` if you want them completely silent, or use the YAML callback plugin (`ANSIBLE_STDOUT_CALLBACK=yaml`) which formats output more readably than the default JSON dump.

If you want to suppress the full traceback from the failed task itself (the big red block), set `ANSIBLE_DISPLAY_FAILED_STDERR=yes` in your ansible.cfg. That shows only stderr from failed commands rather than the entire result dictionary.
