# Problem upgrading to Ansible 2.19

**URL:** <https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144>\
**Category:** Get Help\
**Tags:** azure, ee\
**Created:** [January 21, 2026, 10:44am UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144 "2026-01-21T10:44:19Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![ildjarn](https://avatars.discourse-cdn.com/v4/letter/i/8491ac/32.png) [@ildjarn](https://forum.ansible.com/u/ildjarn)\
**Post date:** [January 21, 2026, 10:44am UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/1 "2026-01-21T10:44:19Z")

</div>

Hello,

I am trying to build a new EE with Ansible 2.19.

- Is there a minimal Python version requirement for Ansible 2.19? I couldn’t find one. I need the Azure collection, and aumqp (one of the dependencies) fails to build with Python 3.14, so I’m using Python 3.12 at the moment.

I changed the EE definition to use 2.19:

```auto
ansible_core:
    package_pip: ansible-core<2.20

```

(from `<2.19`). Nothing else changed in the EE definition.

I now get an error `ModuleNotFoundError: No module named 'ansible.module_utils.common.sentinel'` when running a playbook. Searching for this error gave me zero results, so I have no idea where to start finding out what’s going wrong.

Full stack trace:

```auto
  Traceback (most recent call last):
    File "/tmp/ansible_Testplaybook_payload_csu_j205/ansible_Testplaybook_payload.zip/ansible/module_utils/_internal/_ansiballz/_loader.py", line 35, in run_module
    File "/tmp/ansible_Testplaybook_payload_csu_j205/ansible_Testplaybook_payload.zip/ansible/module_utils/_internal/_ansiballz/_loader.py", line 62, in _run_module
    File "<frozen runpy>", line 226, in run_module
    File "<frozen runpy>", line 98, in _run_module_code
    File "<frozen runpy>", line 88, in _run_code
    File "/tmp/ansible_Testplaybook_payload_csu_j205/ansible_Testplaybook_payload.zip/ansible/legacy/Testplaybook.py", line 72, in <module>
    File "/usr/local/lib/python3.12/site-packages/ansible/errors/ __init__.py", line 16, in <module>
      from .._internal._errors import _error_utils
    File "/usr/local/lib/python3.12/site-packages/ansible/_internal/_errors/_error_utils.py", line 13, in <module>
      from ansible.module_utils._internal import _ambient_context, _event_utils, _messages, _traceback
  ImportError: cannot import name '_ambient_context' from
  'ansible.module_utils._internal'
  (/tmp/ansible_Testplaybook_payload_csu_j205/ansible_Testplaybook_payload.zip/ansible/module_utils/_internal/ __init__.py)

  During handling of the above exception, another exception occurred:

  Traceback (most recent call last):
    File "/runner/.ansible/tmp/ansible-tmp-1768991758.9563625-22-263207363273348/AnsiballZ_Testplaybook.py", line 266, in <module>
      _ansiballz_main(
    File "/runner/.ansible/tmp/ansible-tmp-1768991758.9563625-22-263207363273348/AnsiballZ_Testplaybook.py", line 260, in _ansiballz_main
      invoke_module(zipped_mod, encoded_params)
    File "/runner/.ansible/tmp/ansible-tmp-1768991758.9563625-22-263207363273348/AnsiballZ_Testplaybook.py", line 140, in invoke_module
      _loader.run_module(
    File "/tmp/ansible_Testplaybook_payload_n7ywkp0a/ansible_Testplaybook_payload.zip/ansible/module_utils/_internal/_ansiballz/_loader.py", line 43, in run_module
    File "/tmp/ansible_Testplaybook_payload_n7ywkp0a/ansible_Testplaybook_payload.zip/ansible/module_utils/_internal/_ansiballz/_loader.py", line 77, in _handle_exception
    File "/tmp/ansible_Testplaybook_payload_n7ywkp0a/ansible_Testplaybook_payload.zip/ansible/module_utils/common/json.py", line 85, in get_module_encoder
    File "/tmp/ansible_Testplaybook_payload_n7ywkp0a/ansible_Testplaybook_payload.zip/ansible/module_utils/common/json.py", line 75, in get_encoder
    File "/tmp/ansible_Testplaybook_payload_n7ywkp0a/ansible_Testplaybook_payload.zip/ansible/module_utils/_internal/_json/ __init__.py", line 18, in get_encoder_decoder
    File "/tmp/ansible_Testplaybook_payload_n7ywkp0a/ansible_Testplaybook_payload.zip/ansible/module_utils/_internal/_json/ __init__.py", line 39, in get_serialization_module
    File "/usr/lib64/python3.12/importlib/ __init__.py", line 90, in import_module
      return _bootstrap._gcd_import(name[level:], package, level)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
    File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
    File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
    File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
    File "<frozen importlib._bootstrap_external>", line 999, in exec_module
    File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
    File "/tmp/ansible_Testplaybook_payload_n7ywkp0a/ansible_Testplaybook_payload.zip/ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py", line 11, in <module>
    File "/tmp/ansible_Testplaybook_payload_n7ywkp0a/ansible_Testplaybook_payload.zip/ansible/module_utils/_internal/_json/_profiles/ __init__.py", line 268, in __init_subclass__
    File "/usr/local/lib/python3.12/site-packages/ansible/_internal/ __init__.py", line 15, in get_controller_serialize_map
      from ansible._internal._templating import _lazy_containers
    File "/usr/local/lib/python3.12/site-packages/ansible/_internal/_templating/_lazy_containers.py", line 21, in <module>
      from ansible.utils.sentinel import Sentinel
    File "/usr/local/lib/python3.12/site-packages/ansible/utils/sentinel.py", line 8, in <module>
      from ansible.module_utils.common.sentinel import Sentinel # pylint: disable=unused-import
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  ModuleNotFoundError: No module named 'ansible.module_utils.common.sentinel'

```

Version info:

```auto
ansible-playbook [core 2.19.5]
  config file = /runner/project/ansible.cfg
  configured module search path = ['/runner/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules', '/runner/project/plugins/modules']
  ansible python module location = /usr/local/lib/python3.12/site-packages/ansible
  ansible collection location = /runner/requirements_collections:/runner/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible-playbook
  python version = 3.12.12 (main, Jan 8 2026, 00:00:00) [GCC 11.5.0 20240719 (Red Hat 11.5.0-14)] (/usr/bin/python3.12)
  jinja version = 3.1.6
  pyyaml version = 6.0.3 (with libyaml v0.2.5)
Using /runner/project/ansible.cfg as config file

```

Anyone has an idea what might go wrong?

---

<div class="post-metadata">

**Author:** ![BoerBart](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/boerbart/32/10083_2.png) [@BoerBart](https://forum.ansible.com/u/BoerBart)\
**Post date:** [January 21, 2026, 11:00am UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/2 "2026-01-21T11:00:28Z")

</div>

My two cents, as I’m not certain what the problem could be.

As far as i can find, Python \>=3.11 works with Ansible 2.19.

My first thought would be that either the module has been deprecated, or that the name has changed over time, but that’s just me guessing.

Module is still available: [ansible/lib/ansible/module\_utils/common/sentinel.py at devel · ansible/ansible · GitHub](https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/common/sentinel.py)

---

<div class="post-metadata">

**Author:** ![ildjarn](https://avatars.discourse-cdn.com/v4/letter/i/8491ac/32.png) [@ildjarn](https://forum.ansible.com/u/ildjarn)\
**Post date:** [January 21, 2026, 11:53am UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/3 "2026-01-21T11:53:58Z")

</div>

I missed a part of the trace.

The error seems to be in line 72 of my script, which is:  
`from ansible.errors import AnsibleError`

which results in: ImportError: cannot import name ‘\_ambient\_context’ from ‘ansible.module\_utils.\_internal’

---

<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:** [January 21, 2026, 4:49pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/4 "2026-01-21T16:49:29Z")

</div>

it seems you have ‘mixed’ ansible installations, running 2.19 but using lib/ansible from a previous version

---

<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:** [January 21, 2026, 5:22pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/5 "2026-01-21T17:22:57Z")

</div>

> [@ildjarn](#):
>
> - Is there a minimal Python version requirement for Ansible 2.19? I couldn’t find one.

There is: it requires Python 3.11+ on the controller. You can find a good overview of Python and PowerShell requirements and useful dates for all versions since 2.9 here: [Releases and maintenance — Ansible Core Documentation](https://docs.ansible.com/projects/ansible-core/devel/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix)

---

<div class="post-metadata">

**Author:** ![ildjarn](https://avatars.discourse-cdn.com/v4/letter/i/8491ac/32.png) [@ildjarn](https://forum.ansible.com/u/ildjarn)\
**Post date:** [January 21, 2026, 8:25pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/6 "2026-01-21T20:25:02Z")

</div>

That’s very strange.

My execution-environment.yml:

```auto
---
version: 3
images:
  base_image:
    name: quay.io/centos/centos:stream9
dependencies:
  python_interpreter:
    package_system: python3.12
    python_path: /usr/bin/python3.12
  ansible_core:
    package_pip: ansible-core<2.20
  ansible_runner:
    package_pip: ansible-runner
  galaxy: requirements.yml
  system: bindep.txt
  python: requirements.txt

```

What’s wrong/missing about this? The requirements/bindep files don’t contain anything related to ansible itself.

bindep.txt:

```auto
cmake [platform:rpm compile]
epel-release [platform:rpm]
gcc [platform:rpm compile]
gcc-c++ [platform:rpm]
git-core [platform:rpm]
git-lfs [platform:rpm]
krb5-devel [platform:rpm compile]
krb5-workstation [platform:rpm]
libcurl-devel [platform:rpm compile]
libpq-devel [platform:rpm]
make [platform:rpm]
openssl-devel [platform:rpm compile]
podman-remote [platform:rpm]
python-unversioned-command [platform:rpm]
python3.12-devel [platform:rpm compile]
python3.12-psycopg2 [platform:rpm]
redhat-rpm-config [platform:rpm]
rsync [platform:rpm]
sshpass [platform:rpm]
subversion [platform:rpm]
unzip [platform:rpm]
zip [platform:rpm]

```

requirements.txt:

```auto
adal
bs4
cryptography
git+https://github.com/ansible/ansible-sign
ncclient
openpyxl
paramiko
pexpect>=4.5
phonenumbers
pickledb
publicsuffixlist
pyOpenSSL
pykerberos
pypsrp[kerberos,credssp]
python-daemon
pywinrm
pywinrm[kerberos,credssp]
pyyaml
receptorctl
requests
requests-credssp
six
toml
unidecode
xlsxwriter
zeep
meraki
msrestazure
ntc_templates
pynetbox

```

requirements.txt:

```auto
---
collections:
  - name: ansible.netcommon
  - name: ansible.posix
  - name: ansible.utils
  - name: ansible.windows
  - name: awx.awx
  - name: azure.azcollection
  - name: cisco.asa
  - name: cisco.ios
  - name: cisco.meraki
  - name: community.azure
  - name: community.crypto
  - name: community.general
  - name: community.network
  - name: community.windows
  - name: fortinet.fortios
  - name: microsoft.ad
  - name: netbox.netbox

```

---

<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:** [January 21, 2026, 9:01pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/7 "2026-01-21T21:01:02Z")

</div>

I tried building that EE and it worked fine. I was able to run a simple playbook with ansible-navigator:

```yaml
- hosts: localhost
  tasks:
    - debug:
        msg: hello

```

---

<div class="post-metadata">

**Author:** ![ildjarn](https://avatars.discourse-cdn.com/v4/letter/i/8491ac/32.png) [@ildjarn](https://forum.ansible.com/u/ildjarn)\
**Post date:** [January 22, 2026, 6:30am UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/8 "2026-01-22T06:30:39Z")

</div>

Simle test jobs worked fine in my EE as well, but once I started doing fancy stuff like `from ansible.errors import AnsibleError` the excrement hit the rotating equipment.

---

<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:** [January 22, 2026, 6:42am UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/9 "2026-01-22T06:42:49Z")

</div>

Do you have a simple reproducer? `from ansible.errors import AnsibleError` is not something you can do directly from a playbook. Are you writing own plugins?

---

<div class="post-metadata">

**Author:** ![ildjarn](https://avatars.discourse-cdn.com/v4/letter/i/8491ac/32.png) [@ildjarn](https://forum.ansible.com/u/ildjarn)\
**Post date:** [January 22, 2026, 9:54am UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/10 "2026-01-22T09:54:20Z")

</div>

Test playbook:

```auto
---
- name: Testmodule
  hosts: localhost
  gather_facts: false

  tasks:
    - name: A simple module
      testmodule:
        fail: False

    - name: A simple module
      testmodule:
        fail: True

```

testmodule.py:

```auto
from ansible.errors import AnsibleError
from ansible.module_utils.basic import AnsibleModule

def run_module():
    module_args = dict(fail=dict(type="bool", required=True))

    # Module definitie, inclusief verplichte en afhankelijke parameters
    module = AnsibleModule(
        argument_spec=module_args,
    )

    # Resultaatobject
    result = dict(changed=False)
    if module.params["fail"]:
        module.fail_json("Test job fails", **result)
    module.exit_json(**result)

def main():
    run_module()

if __name__ == " __main__":
    main()

```

If I comment out the first line, the playbook works. If I add the import, the playbook stops with the `ImportError: cannot import name '_ambient_context' from 'ansible.module_utils._internal'` error.

---

<div class="post-metadata">

**Author:** ![ildjarn](https://avatars.discourse-cdn.com/v4/letter/i/8491ac/32.png) [@ildjarn](https://forum.ansible.com/u/ildjarn)\
**Post date:** [January 22, 2026, 1:48pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/11 "2026-01-22T13:48:44Z")

</div>

When I run the EE locally (docker run -it image bash), and start /usr/bin/python3.12, I can successfully run ‘from ansible.errors import AnsibleError’. It’s just when it’s done from within a module in a playbook started in AWX that it fails.

---

<div class="post-metadata">

**Author:** ![shrews](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/shrews/32/10142_2.png) [@shrews](https://forum.ansible.com/u/shrews)\
**Post date:** [January 22, 2026, 4:58pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/12 "2026-01-22T16:58:23Z")

</div>

> [@ildjarn](#):
>
> `from ansible.errors import AnsibleError`

Remove that import line from your module. Modules should not import from the `ansible` package, except for `module_utils`.

---

<div class="post-metadata">

**Author:** ![ildjarn](https://avatars.discourse-cdn.com/v4/letter/i/8491ac/32.png) [@ildjarn](https://forum.ansible.com/u/ildjarn)\
**Post date:** [January 23, 2026, 6:54am UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/13 "2026-01-23T06:54:08Z")

</div>

This has always worked since I started using Ansible (around 4 or 5 years ago).  
As far as I know you can use all modules that are installed on the machine that runs the code, and Ansible will also copy the module\_utils modules to the machine that runs the code. Since the code is running on localhost, I should be able to use the ansible module itself.

I found the following:

> Ansible will only transfer referenced module\_util codes from either ansible or ansible\_collections to the remote. Anything else needs to be installed as a normal Python module on the remote to be used.

When checking with ‘pip list’ I see that ansible-core 2.19.5 is installed:

```json
{
  "name": "ansible-core", 
  "version": "2.19.5",
  "location": "/usr/local/lib/python3.12/site-packages",
  "installer": "pip"
}

```

So I should be able to use this Python module. Most things work (e.g. `from ansible.plugins.lookup import LookupBase`, or `from ansible.utils.display import Display`) but the error import fails.

---

<div class="post-metadata">

**Author:** ![shrews](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/shrews/32/10142_2.png) [@shrews](https://forum.ansible.com/u/shrews)\
**Post date:** [January 23, 2026, 1:53pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/14 "2026-01-23T13:53:58Z")

</div>

See [Need explanation that modules can only import from `module_utils` within the `ansible` namespace · Issue #3442 · ansible/ansible-documentation · GitHub](https://github.com/ansible/ansible-documentation/issues/3442) for more info.

---

<div class="post-metadata">

**Author:** ![ildjarn](https://avatars.discourse-cdn.com/v4/letter/i/8491ac/32.png) [@ildjarn](https://forum.ansible.com/u/ildjarn)\
**Post date:** [January 23, 2026, 2:12pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/15 "2026-01-23T14:12:44Z")

</div>

I understand the rationale behind ‘you should only include from ansible.module\_utils, because we won’t copy everything to the remote node’, but the ‘remote node’ is localhost, so the ansible Python module is installed. I checked os.path in a module, and /usr/local/lib/python3.12/dist-packages is there.

Oh well. I’ll rewrite everything to use something else than AnsibleError…

FWIW:  
`python3 'path/to/module-with-errorimport' ansibleargs.json` works with `from ansible.errors import AnsibleError`.

---

<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:** [January 23, 2026, 8:52pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/16 "2026-01-23T20:52:54Z")

</div>

If you’re writing a collection, I’d suggest to run `ansible-test sanity` on it. It would have warned you about this.

---

<div class="post-metadata">

**Author:** ![shertel](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/shertel/32/1241_2.png) [@shertel](https://forum.ansible.com/u/shertel)\
**Post date:** [January 23, 2026, 11:18pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/17 "2026-01-23T23:18:52Z")

</div>

> [@ildjarn](#):
>
> I understand the rationale behind ‘you should only include from ansible.module\_utils, because we won’t copy everything to the remote node’, but the ‘remote node’ is localhost, so the ansible Python module is installed. I checked os.path in a module, and /usr/local/lib/python3.12/dist-packages is there.

Importing `ansible.errors` doesn’t fail because the `ansible` Python module isn’t installed. It fails because `testmodule` doesn’t have access to the `ansible.module_utils` that `ansible.errors` needs. To include those in the [zipfile](https://docs.ansible.com/projects/ansible/latest/dev_guide/developing_program_flow_modules.html#ansiballz-framework), you’d need to add imports for them.

> Oh well. I’ll rewrite everything to use something else than AnsibleError…

Emit errors using JSON (for example, using [AnsibleModule.fail\_json()](https://github.com/ansible/ansible/blob/v2.19.5/lib/ansible/module_utils/basic.py#L1537)), or you could use your own exception.

Or, why not write an action plugin, lookup plugin, or filter/test plugin, which run on the control node by design?

---

<div class="post-metadata">

**Author:** ![ildjarn](https://avatars.discourse-cdn.com/v4/letter/i/8491ac/32.png) [@ildjarn](https://forum.ansible.com/u/ildjarn)\
**Post date:** [January 26, 2026, 6:51am UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/18 "2026-01-26T06:51:51Z")

</div>

- I install python module datetime’. I can use `from datetime.datetime include X` in my code.
- I install python module ‘requests’, I can include `from requests include X` in my code.
- I install python module ‘ansible’, I can not `from ansible.errors include Y` in my code.

Sorry, I don’t see why. Including ansible.errors on a node that has the ansible module installed has always worked, until 2.19.  
That’s a breaking change, and should have been mentioned in the release notes.

---

<div class="post-metadata">

**Author:** ![shertel](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/shertel/32/1241_2.png) [@shertel](https://forum.ansible.com/u/shertel)\
**Post date:** [January 26, 2026, 1:17pm UTC](https://forum.ansible.com/t/problem-upgrading-to-ansible-2-19/45144/19 "2026-01-26T13:17:38Z")

</div>

> Sorry, I don’t see why. Including ansible.errors on a node that has the ansible module installed has always worked, until 2.19.

I explained why. Look at the traceback, it is NOT complaining it can’t find ansible.errors, it’s complaining about module\_utils that are not packaged in the zipfile. From within the module context, you have a subset of module\_utils available (controlled by explicitly importing things in ansible.module\_utils). You’d need to add the following imports to your module to make sure the zipfile includes everything necessary:

```auto
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils._internal import _ambient_context # Note: anything named with a leading underscore is private, and can break, be renamed, etc at any time
from ansible.module_utils.common import yaml

```

You can expect this kind of thing to keep “breaking” because it’s not public API. Follow the docs link above for more clarification.
