Summary
This bug is similar to, but not quite like, #75120 and #17894.
The documentation says roles are searched for in 4 places:
- collections,
./roles/ in the directory containing the playbook file,
- In
roles_path
- directly next to the playbook file
Additionally, they will also be picked up from a 5th place: the working directory where ansible-playbook is run.
And, if a role cannot be found, the error message's list of places the role was not found DOES NOT list the current working directory, despite the fact that it is searched.
I discovered this when (with roles_path = ./roles in ansible.cfg) I moved my playbooks into a ./playbooks subdir, and then accidentally ran ansible-galaxy role init blah instead of ansible-galaxy role init roles/blah.
According to an LLM, and verified by me reading the code, the issue arises when the role loader falls back to unfrackpath(role_name). The basedir argument defaults to None, which results in searching the current directory.
Issue Type
Bug Report
Component Name
RoleDefinition
Ansible Version
$ ansible --version
ansible [core 2.20.5]
config file = /home/rhaley/.ansible.cfg
configured module search path = ['/home/rhaley/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.14/site-packages/ansible
ansible collection location = /home/rhaley/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.14.4 (main, Apr 16 2026, 00:00:00) [GCC 16.0.1 20260321 (Red Hat 16.0.1-0)] (/usr/bin/python3)
jinja version = 3.1.6
pyyaml version = 6.0.3 (with libyaml v0.2.5)
Configuration
# if using a version older than ansible-core 2.12 you should omit the '-t all'
$ ansible-config dump --only-changed -t all
ANSIBLE_NOCOWS(env: ANSIBLE_NOCOWS) = True
CONFIG_FILE() = /home/rhaley/.ansible.cfg
EDITOR(env: EDITOR) = /usr/bin/vim
INTERPRETER_PYTHON(/home/rhaley/.ansible.cfg) = auto
OS / Environment
Fedora 44. Also reproduces in the ansible-dev-tools dev container.
Steps to Reproduce
#!/usr/bin/env bash
workspace="/tmp/ansible_bug"
[ -x "$workspace" ] && rm -r "$workspace"
mkdir -p "$workspace"
cd "$workspace"
setup () {
# test playbook
mkdir -p playbooks
cat >playbooks/test.yml <<EOF
---
- name: Play to reproduce bug
hosts: localhost
roles:
- testrole
EOF
# role in unorothodox location
mkdir -p roles_dir/testrole/tasks/
cat >roles_dir/testrole/tasks/main.yml <<EOF
---
- ansible.builtin.debug:
msg: "this should not work"
EOF
}
reproduce () {
set -x
# should error, does
cd "$workspace"
ansible-playbook "$workspace/playbooks/test.yml"
# should error, DOES NOT
cd "$workspace/roles_dir"
ansible-playbook "$workspace/playbooks/test.yml"
}
setup
reproduce
Expected Results
Ideally, the role would not be found in either case. If I accidentally created the role in the wrong place, I don't want that covered up because I just happened to run ansible-playbook in the same directory as the role.
Baring that, the documentation would list the current working directory as one of the places searched for roles.
Actual Results
+ cd /tmp/ansible_bug
+ ansible-playbook /tmp/ansible_bug/playbooks/test.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
[ERROR]: the role 'testrole' was not found in /tmp/ansible_bug/playbooks/roles:/home/rhaley/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles:/tmp/ansible_bug/playbooks
Origin: /tmp/ansible_bug/playbooks/test.yml:5:7
3 hosts: localhost
4 roles:
5 - testrole
^ column 7
+ cd /tmp/ansible_bug/roles_dir
+ ansible-playbook /tmp/ansible_bug/playbooks/test.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Play to reproduce bug] *****************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************************
ok: [localhost]
TASK [testrole : ansible.builtin.debug] ******************************************************************************************
ok: [localhost] => {
"msg": "this should not work"
}
PLAY RECAP ***********************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Code of Conduct
Summary
This bug is similar to, but not quite like, #75120 and #17894.
The documentation says roles are searched for in 4 places:
./roles/in the directory containing the playbook file,roles_pathAdditionally, they will also be picked up from a 5th place: the working directory where
ansible-playbookis run.And, if a role cannot be found, the error message's list of places the role was not found DOES NOT list the current working directory, despite the fact that it is searched.
I discovered this when (with
roles_path = ./rolesinansible.cfg) I moved my playbooks into a./playbookssubdir, and then accidentally ranansible-galaxy role init blahinstead ofansible-galaxy role init roles/blah.According to an LLM, and verified by me reading the code, the issue arises when the role loader falls back to
unfrackpath(role_name). Thebasedirargument defaults toNone, which results in searching the current directory.Issue Type
Bug Report
Component Name
RoleDefinition
Ansible Version
Configuration
OS / Environment
Fedora 44. Also reproduces in the ansible-dev-tools dev container.
Steps to Reproduce
Expected Results
Ideally, the role would not be found in either case. If I accidentally created the role in the wrong place, I don't want that covered up because I just happened to run
ansible-playbookin the same directory as the role.Baring that, the documentation would list the current working directory as one of the places searched for roles.
Actual Results
Code of Conduct