Using facts in 'tasks_from' with 'include_role' will load the same task file for all hosts.

I was trying to use different entry points for a role depending on ansible_facts['system'] var.

The following example role has only 2 task files:

Linux.yml:

---
- name: Assert
  ansible.builtin.assert:
    that:
      - ansible_facts['system'] == 'Linux'
...

Win32NT.yml:

---
- name: Assert
  ansible.builtin.assert:
    that:
      - ansible_facts['system'] == 'Win32NT'
...

Playbook test1.yml:

---
- name: Play
  hosts: all
  tasks:
    - name: Include role
      ansible.builtin.include_role:
        name: test
        tasks_from: "{{ ansible_facts['system'] }}"
...

Lets say we have a Windows host named win1, and a Linux host named lin1

The problem only occurs when you mix Windows and Linux hosts in the same run:

ansible-playbook test1.yml -l 'win1,lin1'
PLAY [Play] *********************************************************************************************************************************

TASK [Include role] *************************************************************************************************************************
included: test for lin1, win1

TASK [test : Assert] ************************************************************************************************************************
ok: [lin1] => 
    changed: false
    msg: All assertions passed
[ERROR]: Task failed: Action failed: Assertion failed
Origin: /home/carlos/repos/vfmsa_roles/roles/test/tasks/Linux.yml:2:3

1 ---
2 - name: Assert
    ^ column 3

fatal: [win1]: FAILED! => 
    assertion: ansible_facts['system'] == 'Linux'
    changed: false
    evaluated_to: false
    msg: Assertion failed

PLAY RECAP **********************************************************************************************************************************
lin1              : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
win1              : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

Ansible is using Linux.yml for all hosts.

There are no issues when running the playbook with each host independently.

Is what I’m trying to do legal? If not: why?

Ansible version: 2.19.0
The same problem occurs with 2.18

I believe we have a bug report detailing this already:

I’m not completely sure is the same problem. But anyway, that was supposed to be fixed 3 years ago.

What I want to know first is how to approach this. Is this a known bug? Am I doing something out of best practices? Is it just me? Can someone reproduce it? Should I open a bug report?

As it was already mentioned, yes, it is a known bug reported in a still open issue: include_role sometimes ignores dynamic vars_from parameter · Issue #66497 · ansible/ansible · GitHub

The bug manifests itself on all *_from options. The bug above specifically mentions vars_from in its title but it applies to tasks_from too as you are seeing in your playbook.

IncludedFile: store _from args for proper deduplication by mkrizek · Pull Request #85628 · ansible/ansible · GitHub and here is fix

Awsome!

That did the trick. thank you.