# How to retrieve fact with a dynamic fact name?

**URL:** <https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431>\
**Category:** Get Help\
**Created:** [September 6, 2025, 6:20pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431 "2025-09-06T18:20:19Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![matthew\_exon](https://avatars.discourse-cdn.com/v4/letter/m/edb3f5/32.png) [@matthew\_exon](https://forum.ansible.com/u/matthew_exon)\
**Post date:** [September 6, 2025, 6:20pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/1 "2025-09-06T18:20:19Z")

</div>

I’m trying to call out to a task list with `include_tasks` where I want the task list to set a particular named fact, passed as a variable to the task list. I can set the fact, but it’s not appearing in `ansible_facts` as I would expect.

Here’s a playbook with five tasks:

1. Sets the fact according to a fact name passed as a variable
2. Retrieves the fact, proving it’s set
3. Gets a fact from `ansible_facts`, showing how I expect that to work
4. Gets the fact by name, which doesn’t work as I expect
5. Gets the fact according to a fact name passed as a variable, what I’m trying to achieve

Can someone explain why step 4 doesn’t work, and how it should be done?

```
---
- hosts: all
  tasks:
  - name: Set first fact with dynamic fact name
    ansible.builtin.set_fact: {"{{ fact_name }}":"hello world"}
    vars:
      fact_name: "fact1"
  - name: Get first fact as variable - WORKS
    ansible.builtin.debug:
      var: fact1
  - name: Get processor cores from ansible_facts - WORKS
    ansible.builtin.debug:
      var: ansible_facts["processor_cores"]
  - name: Get first fact from ansible_facts - DOESN'T WORK
    ansible.builtin.debug:
      var: ansible_facts["fact1"]
  - name: Get first fact from ansible_facts with dynamic fact name - DOESN'T WORK
    ansible.builtin.debug:
      var: ansible_facts[fact_name]
    vars:
      fact_name: "fact1"

```

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [September 6, 2025, 6:29pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/2 "2025-09-06T18:29:46Z")

</div>

The reason is that `ansible.builtin.set_fact` does not create facts, but variables (more precisely: host-level variables) with a fixed value. The same happens if you don’t use a dynamic fact name, but a static fact name. You can fix that by making it a cacheable fact by setting `cacheable=true`, which will create a host-level variable _and_ a “real” Ansible fact:

```auto
  - name: Set first fact with dynamic fact name
    ansible.builtin.set_fact:
      "{{ fact_name }}": hello world
      cacheable: true
    vars:
      fact_name: "fact1"

```

See [ansible.builtin.set\_fact module – Set host variable(s) and fact(s). — Ansible Community Documentation](https://docs.ansible.com/ansible/devel/collections/ansible/builtin/set_fact_module.html#parameter-cacheable) for more infos.

---

<div class="post-metadata">

**Author:** ![matthew\_exon](https://avatars.discourse-cdn.com/v4/letter/m/edb3f5/32.png) [@matthew\_exon](https://forum.ansible.com/u/matthew_exon)\
**Post date:** [September 6, 2025, 6:51pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/3 "2025-09-06T18:51:09Z")

</div>

Thanks! I saw `cacheable: true` and could see that it was something important, but I couldn’t make head or tail of the explanation. 7 levels of precedence sounds like acute demonology. I used your example and now I made it all go the way I wanted.

> The reason is that `ansible.builtin.set_fact` does not create facts, but variables

Perhaps it should be called `set_variable`, and have an option `set_fact: true`? Or, if that can’t work for demonology-related reasons, perhaps a slightly simpler warning in the docs?

---

<div class="post-metadata">

**Author:** ![felixfontein](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/felixfontein/32/7530_2.png) [@felixfontein](https://forum.ansible.com/u/felixfontein)\
**Post date:** [September 7, 2025, 2:32pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/4 "2025-09-07T14:32:45Z")

</div>

Well, to be honest, I wasn’t really aware of this behavior before myself, since I always used `set_fact` as a sort of “set variable to a constant value” (as opposed to `vars`, which sets them to something that’s evaluated on every usage). I agree that `set_variable` would be a better name, but I guess the naming comes from the early history of Ansible and hasn’t been changed since it’s used everywhere.

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [September 8, 2025, 1:51pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/5 "2025-09-08T13:51:48Z")

</div>

> [@felixfontein](#):
>
> ally aware of this behavior before myself, since I always used `set_fact` as a sort of “set variabl

There is an irc log somewhere with a 3 week flame war about naming `set_fact` (originally `set_var` IIRC)

---

<div class="post-metadata">

**Author:** ![anon81884396](https://avatars.discourse-cdn.com/v4/letter/a/b782af/32.png) [@anon81884396](https://forum.ansible.com/u/anon81884396)\
**Post date:** [September 8, 2025, 3:42pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/6 "2025-09-08T15:42:48Z")

</div>

> Perhaps it should be called `set_variable` , and have an option `set_fact: true` ?

Please don’t give them any ideas ☹

Seagulls are called seagulls despite them not being exclusively tied to the sea, humanity moves on and doesn’t need to rewrite every piece of literature in existence for correctness sake. I say this with peace and love, of course!

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [September 8, 2025, 3:46pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/7 "2025-09-08T15:46:55Z")

</div>

my proposal looong ago was:

```auto
set_var: value=x scope=host|play|fact

```

---

<div class="post-metadata">

**Author:** ![matthew\_exon](https://avatars.discourse-cdn.com/v4/letter/m/edb3f5/32.png) [@matthew\_exon](https://forum.ansible.com/u/matthew_exon)\
**Post date:** [September 10, 2025, 5:22am UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/8 "2025-09-10T05:22:28Z")

</div>

In my particular case, I wanted a way to set a “thing” (fact, variable, don’t mind) with a name string and retrieve it with the same name string. Having an `ansible_vars` array similar to `ansible_facts` would have worked just as well. But I couldn’t find anything like that. Seems like there’s a surprising asymmetry there.

---

<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:** [September 10, 2025, 11:01am UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/9 "2025-09-10T11:01:29Z")

</div>

You can do what you want if you make the dynamic part not a top-level variable. Instead, store the dynamic names as keys in a known named dict. Consider this playbook:

```yaml
---
# matthew_exon_00.yml
- name: Dynamic fact name
  hosts: localhost
  gather_facts: false
  tasks:
    - name: Initialize our dynamic fact store
      ansible.builtin.set_fact:
        dyn_fact_store: {}

    - name: Add some dynamic facts
      ansible.builtin.set_fact:
        dyn_fact_store: '{{ dyn_fact_store | combine({dname: dvalue}) }}'
      vars:
        dvalue: '{{ 100 | ansible.builtin.random }}'
      loop: ['apple', 'banana', 'grape']
      loop_control:
        loop_var: dname

    - name: Dump our dynamic fact store
      ansible.builtin.debug:
        var: dyn_fact_store

```

which produces this (varies from run to run of course):

```plaintext
TASK [Dump our dynamic fact store] ****
ok: [localhost] => {
    "dyn_fact_store": {
        "apple": "73",
        "banana": "18",
        "grape": "10"
    }
}

```

These aren’t really _facts_ as felixfontein pointed out, unless you also set `cacheable: true` and enable caching .

---

<div class="post-metadata">

**Author:** ![matthew\_exon](https://avatars.discourse-cdn.com/v4/letter/m/edb3f5/32.png) [@matthew\_exon](https://forum.ansible.com/u/matthew_exon)\
**Post date:** [September 10, 2025, 11:17am UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/10 "2025-09-10T11:17:35Z")

</div>

Yes, this is probably cleaner. Still, it’s slightly more verbose than just setting `cacheable: true`, which is working for now.

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [September 10, 2025, 2:29pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/11 "2025-09-10T14:29:53Z")

</div>

fun note, this actually creates 2 copies of the variable, the normal `set_fact` creates a host scoped variable at higher precedence than facts, when you set `cacheable` you ALSO create a copy and insert it into `ansible_facts`.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/ansible/original/1X/1882d9a01da5d8996a862359b0913cc568a39b84.svg) [@system](https://forum.ansible.com/u/system)\
**Post date:** [October 10, 2025, 2:30pm UTC](https://forum.ansible.com/t/how-to-retrieve-fact-with-a-dynamic-fact-name/44431/12 "2025-10-10T14:30:51Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
