Ansible-core 2.19

A practical, field-tested guide to what changed, what’s still broken, and how to upgrade safely (Oct 26, 2025)

Ansible-core 2.19 is the biggest plumbing change since collections. It delivered the Data Tagging overhaul and a stricter templating engine, which in turn surfaced long-hidden assumptions in playbooks, roles, and collections—especially in networking. This guide explains the why, catalogs today’s known issues, and gives you copy-pasteable mitigations and an upgrade plan that won’t melt your pipelines.


TL;DR (for busy humans)

  • 2.19 tightened templating & typing (“tagged” values) and changed parts of module argument loading. That exposed brittle Jinja/JMESPath patterns and broke some “direct execution” flows used by network content. (Ansible Documentation)

  • ansible.netcommon initially didn’t mesh with 2.19’s new behavior; vendor collections relying on it (Arista, Cisco, Juniper, etc.) were impacted until follow-up fixes landed. Do not upgrade core alone—move core + netcommon + vendor collections together after testing. (Ansible)

  • If you need a stable baseline today:

    pip install "ansible-core<2.19"     # or
    pip install "ansible~=11"
    

    Then ready your codebase for 2.19 using the steps below. (Some vendor ecosystems—e.g., arista.avd 5.x—explicitly support up to 2.18.x.) (avd.arista.com)


What actually changed (and why it matters)

1) Data Tagging & stricter templating

Values flowing through Jinja are now explicitly typed/tagged rather than always coerced to strings. That’s more correct and safer, but it breaks patterns that counted on implicit coercion—especially JMESPath via community.general.json_query, which expects raw arrays/strings/numbers. Typical symptoms:

  • _AnsibleTaggedStr or “invalid type for value” JMESPath errors
  • Loop expressions failing unless the input is a concrete list

👉 Action: Prefer pure Jinja (selectattr, map, list, sort) or coerce to plain JSON before json_query. See recipes below. (Ansible Documentation)

2) Network content & “direct execution”

Core 2.19 refactors around how action modules patch/parse arguments. ansible.netcommon had been patching internals (e.g., _load_params, sys.argv) to enable “direct execution.” 2.19 broke that path until collection/core shims arrived. 👉 Upgrade together and target a netcommon release that states 2.19 compatibility. (Ansible)


The open 2.19 issues you should actually care about (curated)

Source: GitHub issues filtered for is:issue state:open 2.19 (pages 1–2), captured Oct 26, 2025. Use these summaries to decide what to refactor vs. what to pin. (GitHub)

Run control & UX

  • Ctrl+C no longer stops entire play (regression): interrupt cancels the current task but play continues. Impact: harder to abort cleanly. Mitigate: structure plays into smaller units; abort between plays; monitor fix discussion. (GitHub)

Connectivity & privilege escalation

  • ping fails with “unknown encoding: idna” on 2.19 (2.18 OK). Mitigate: ensure idna is installed in your EE/venv; if still broken, pin to <2.19 until fixed. (GitHub)
  • sudo without become password no longer works in some flows. Mitigate: supply become_pass explicitly or hold at 2.18 pending resolution. (GitHub)

Templating, Jinja, and data tagging fallout

  • Jinja macros: “pass by value” surprises under 2.19 tagging. Mitigate: cast/serialize before macro calls; return new structures instead of mutating. (GitHub)
  • vars_files “skipped” message is misleading when templated paths are used. Mitigate: load with include_vars in pre_tasks and explicit paths. (GitHub)
  • default() after deepcopy breaks vs 2.18. Mitigate: avoid deepcopy on templated structures; compute at task runtime; cast to natives first. (GitHub)
  • Inline-vaulted vs file-vaulted variables render inconsistently. Mitigate: prefer file-vault in re-rendered contexts. (GitHub)
  • Loop templates broken by “native types.” Ensure loop inputs are actual lists (| list, | from_yaml). (GitHub)
  • transform_to_native_types(..., redact=True) ineffective in some paths. Mitigate: pre-serialize to JSON then redact. (GitHub)
  • delegate_to evaluated before task condition → undefined var errors on skipped tasks. Mitigate: precompute target only when condition is true, or guard with is defined. (GitHub)
  • module_defaults for setup don’t affect implicit fact gathering (2.19 regression). Mitigate: call explicit setup: with desired options. (GitHub)
  • Excessively long/complex error messages when filters raise AnsibleFilter*Error. Mitigate: not functional, but expect noisy traces. (GitHub)

Heads-up for networkers: alongside the core issues above, netcommon published patches to restore direct execution behavior on 2.19.1+; upgrade the trio (core + netcommon + vendor collection) together. (Ansible)


Failure patterns & quick fixes

Pattern A — json_query explodes with tagged values (JMESPath type errors)

Symptom: _AnsibleTaggedStr / “invalid type for value” during json_query. Fix (prefer pure Jinja):

{{ items
   | selectattr('state','equalto','present')
   | map(attribute='version')
   | map('string')
   | list
   | sort }}

If you must keep JMESPath, coerce first:

{{ items | to_json | from_json
   | community.general.json_query('sort([?state==`present`].version)') }}

(Ansible)

Pattern B — Loop/iterator fails after upgrade

Symptom: loop: "{{ templated_expr }}" errors. Fix: ensure templated_expr is a concrete list: append | list or | from_yaml. (GitHub)

Pattern C — Network collections don’t run or crash at import

Symptom: Vendor modules fail mysteriously after upgrading only core. Fix: upgrade together with compatible ansible.netcommon + vendor collection versions; if your vendor docs state a ceiling (e.g., AVD ≤ 2.18.x), respect it until they publish 2.19 support. (Ansible)


A safe, repeatable upgrade plan

  1. Freeze what works while you prep:

    pip install "ansible-core<2.19"       # or
    pip install "ansible~=11"
    

    Pin collections in collections/requirements.yml and Python deps in requirements.txt. (avd.arista.com)

  2. Use Execution Environments (EEs) (or at least a venv) so you can test matrix combos without touching prod.

  3. Read the 2.19 Porting Guide and note templating & plugin-loader changes that affect you. Build a checklist for: filters, lookups, callback/action/connection plugins. (Ansible Documentation)

  4. CI the matrix: run representative plays/roles against:

    • ansible-core 2.18.x vs 2.19.x
    • latest ansible.netcommon and vendor collections Fail fast; file issues where needed. (Ansible Documentation)
  5. Refactor brittle templating: prefer Jinja pipelines; evaluate complex expressions at task runtime (set_fact) instead of vars/ files.

  6. Upgrade in lockstep once green: bump core, netcommon, and vendor collections together (and re-run CI on bugfixes 2.19.x). Watch collection release notes that specifically call out 2.19 adaptations (e.g., community.general, ansible.netcommon). (Ansible Documentation)


Copy-paste snippets you can adopt today

Pin stable lines during transition

# requirements.txt (Python)
ansible-core<2.19
# or choose the community bundle track:
ansible~=11

Hardened Jinja (drop-in for many json_query uses)

{{ mylist
   | selectattr('enabled')
   | map(attribute='name')
   | map('string')
   | list
   | sort }}

Guard delegate_to evaluation

- name: Do thing on computed delegate
  when: target_host is defined and target_host|length>0
  delegate_to: "{{ target_host }}"
  ansible.builtin.command: /usr/bin/true

Explicit fact gathering defaults until regression is fixed

- name: Gather only minimal facts with my defaults
  ansible.builtin.setup:
    gather_subset:
      - network
      - hardware

(Use explicit task; don’t rely on implicit fact-gather behavior.) (GitHub)


FAQ

Q: Is 2.19 “bad,” or just stricter? A bit of both. The core changes are intentional and generally positive, but they surfaced assumptions (especially around templating and direct execution) that many of us made unconsciously. The porting guide calls out the expected behavior changes; the rest are active regressions being worked through. (Ansible Documentation)

Q: I run AVD/other network collections. What should I do? Follow your vendor’s stated version support (AVD 5.x: 2.15–2.18.x at time of writing). If you need 2.19 features, test with their latest collection + netcommon fixes in an EE, not on your production controller. (avd.arista.com)

Q: My errors got wordier in 2.19. Known. Filter exceptions can produce very long traces right now; expect cleanup over time. (GitHub)


Further reading & trackers

  • Porting Guide — core-2.19 (living doc). (Ansible Documentation)
  • Roadmap — core-2.19 (planned/delayed work). (Ansible Documentation)
  • Data Tagging preview/testing thread (background and implications). (Ansible)
  • Networking breakage & netcommon fixes (direct exec patches and status). (Ansible)
  • Vendor stance example — Arista AVD 5.x (explicit pin to <2.19). (avd.arista.com)
  • Community.general changelog (notes on 2.19-related changes). (Ansible Documentation)
  • GitHub: Open 2.19 issues (pages 1–2) — use to track regressions affecting you. (GitHub)

Conclusion

Treat 2.19 as a planned migration, not a casual bump. The wins—safer templating, clearer types, better long-term hygiene—are real, but only if you refactor brittle template logic and upgrade in lockstep with your collections. Pin now, port deliberately, and let CI be the bouncer at the door.