Skip to content

Absent role in include_role inside of block/rescue leads to unexpected behavior #86721

@noonedeadpunk

Description

@noonedeadpunk

Summary

Original usecase

As collections can not be dependent on an individual roles, and I wanted to re-use an existing standalone role when it's available, but also have an internal very simplified logic when it's not, instead of the failure, I attempted the following workflow:

  1. Create a block/rescue
  2. Put a potentially absent role as include_role: noop_role
  3. Put in rescue include_tasks: simplified_noop
  4. profit

However, I have realized, that block recovery work in an unexpected way for this usecase:

  1. Host is still marked as failed
  2. Tasks for the hosts keep executing
  3. But not all of them. In case a playbook is consisting of multiple roles, even withing the same collection, second role will not be executed, as the host will be seen as failed.

To have that said, a behavior has slightly changed between 2.16.18 and 2.17.14 - while a second role is still ghosted, host was not marked as "failed", which I think was even more confusing to debug...

Issue Type

Bug Report

Component Name

ansible.builtin.include_role

Ansible Version

~/.virtualenvs/ansible/bin/ansible --version
ansible [core 2.19.8]
  config file = None
  configured module search path = ['~/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = ~/.virtualenvs/ansible/lib/python3.11/site-packages/ansible
  ansible collection location = ~/.ansible/collections:/usr/share/ansible/collections
  executable location = ~/.virtualenvs/ansible/bin/ansible
  python version = 3.11.15 (main, Mar  3 2026, 09:26:23) [GCC 13.3.0] (~/.virtualenvs/ansible/bin/python3.11)
  jinja version = 3.1.4
  pyyaml version = 6.0.2 (with libyaml v0.2.5)

Configuration

# ~/.virtualenvs/ansible/bin/ansible-config dump --only-changed -t all
CONFIG_FILE() = None

GALAXY_SERVERS:

OS / Environment

Ubuntu 24.04, Python 3.11.15

Steps to Reproduce

In a simplistic way, this what I have the following layout of a collection:

~/.ansible/collections/ansible_collections$ find noop_ns | sed -e "s/[^-][^\/]*\//  |/g" -e "s/|\([^ ]\)/|-\1/"
noop_ns
  |-noop_collection
  |  |-roles
  |  |  |-trigger
  |  |  |  |-tasks
  |  |  |  |  |-main.yml
  |  |  |-ignored
  |  |  |  |-tasks
  |  |  |  |  |-main.yml
  |  |  |-success
  |  |  |  |-tasks
  |  |  |  |  |-main.yml
  |  |-playbooks
  |  |  |-sample.yml

$ cat noop_ns/noop_collection/roles/trigger/tasks/main.yml

- block:
    - ansible.builtin.include_role:
        name: standalone_role
  rescue:
    - debug:
        msg: Rescue task

- debug:
    msg: Second task

$ cat noop_ns/noop_collection/roles/ignored/tasks/main.yml

- debug:
    msg: This task is ignored

cat noop_ns/noop_collection/roles/success/tasks/main.yml

- debug:
    msg: This second role is executed still

$ cat noop_ns/noop_collection/playbooks/sample.yml

- hosts: localhost
  roles:
    - role: noop_ns.noop_collection.trigger
    - role: noop_ns.noop_collection.success

- hosts: localhost
  roles:
    - role: noop_ns.noop_collection.ignored

Expected Results

  1. Rescued task is not marked as failed
  2. noop_ns.noop_collection.ignored is actually executed

Actual Results

$ ~/.virtualenvs/ansible/bin/ansible-playbook noop_ns.noop_collection.sample
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [ansible.builtin.include_role : standalone_role] **************************************************************************************************************************************************************************************
[ERROR]: the role 'standalone_role' was not found in noop_ns.noop_collection:ansible.legacy:~/.ansible/collections/ansible_collections/noop_ns/noop_collection/playbooks/roles:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:~/.ansible/collections/ansible_collections/noop_ns/noop_collection/playbooks
Origin: ~/.ansible/collections/ansible_collections/noop_ns/noop_collection/roles/trigger/tasks/main.yml:3:15

1 - block:
2     - ansible.builtin.include_role:
3         name: standalone_role
                ^ column 15

fatal: [localhost]: FAILED! => {"changed": false, "reason": "the role 'standalone_role' was not found in noop_ns.noop_collection:ansible.legacy:~/.ansible/collections/ansible_collections/noop_ns/noop_collection/playbooks/roles:~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:~/.ansible/collections/ansible_collections/noop_ns/noop_collection/playbooks"}

TASK [noop_ns.noop_collection.trigger : debug] *********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "Rescue task"
}

TASK [noop_ns.noop_collection.trigger : debug] *********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "Second task"
}

TASK [noop_ns.noop_collection.success : debug] *********************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "This second role is executed still"
}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Code of Conduct

  • I agree to follow the Ansible Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    affects_2.19bugThis issue/PR relates to a bug.has_prThis issue has an associated PR.moduleThis issue/PR relates to a module.verifiedThis issue has been verified/reproduced by maintainer

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions