Troubleshooting “jmespath Not Found” Error in Ansible Despite Package Installation


5 views

When working with Ansible's json_query filter, you might encounter this frustrating scenario where the system insists you need jmespath installed - even when package managers confirm it's already present.

# Typical error message:
fatal: [host]: FAILED! => {"msg": "You need to install \"jmespath\" prior to running json_query filter"}

First, let's confirm what we're seeing:

# Check system package
$ sudo dnf list installed python3-jmespath
python3-jmespath-0.9.0-11.el8.noarch

# Check pip installation
$ pip3 show jmespath
Name: jmespath
Version: 0.9.0
Location: /usr/lib/python3.6/site-packages

This usually happens due to one of these scenarios:

  1. Ansible is using a different Python interpreter than your system default
  2. The environment where Ansible runs doesn't have access to the system packages
  3. Permission issues preventing module loading

First, identify which Python Ansible is actually using:

$ ansible --version
ansible [core 2.12.2]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, Aug 24 2020, 17:57:11) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]

Solution 1: Install for the correct Python environment

$ /usr/bin/python3.6 -m pip install jmespath

Solution 2: Force ansible to use system packages

Add this to your ansible.cfg:

[defaults]
interpreter_python = /usr/bin/python3

Solution 3: Use ansible_python_interpreter

# In your inventory file:
[all:vars]
ansible_python_interpreter=/usr/bin/python3

If you're still having issues, consider these workarounds:

# Use yq (YAML processor) as alternative
- name: Process JSON with yq
  command: yq e '.list1[].name' <(echo "{{ data | to_json }}")
  register: result

# Or use jq if available
- name: Process with jq
  command: jq '.list1[].name' <(echo "{{ data | to_json }}")
  register: result

After applying any solution, test with this simple playbook:

---
- name: Test JMESPath installation
  hosts: localhost
  tasks:
    - name: Test json_query
      debug:
        msg: "{{ [{'name': 'test'}] | json_query('[0].name') }}"

When working with Ansible's powerful json_query filter, encountering the "You need to install jmespath" error while the package is clearly installed can be particularly frustrating. Let's dive into the various aspects of this issue and explore comprehensive solutions.

First, let's verify all possible installation locations:


# Check system package
rpm -qa | grep jmespath

# Check pip installations
pip3 list | grep jmespath
pip3 show jmespath

# Check Python path
python3 -c "import sys; print(sys.path)"

The issue typically stems from one of these scenarios:

  • Ansible running with a different Python interpreter than expected
  • Multiple Python versions causing path confusion
  • Virtual environment isolation issues
  • SELinux context problems (common on RHEL-based systems)

Solution 1: Explicitly Set Python Interpreter

Add this to your ansible.cfg or inventory file:


[defaults]
interpreter_python = /usr/bin/python3

Solution 2: Force Reinstallation for All Users


sudo pip3 install --force-reinstall --ignore-installed jmespath

Solution 3: Virtual Environment Approach

Create a clean virtual environment:


python3 -m venv ansible_venv
source ansible_venv/bin/activate
pip install ansible jmespath

For persistent cases, try this diagnostic playbook:


---
- name: Debug Python environment
  hosts: localhost
  tasks:
    - name: Show Python path
      debug:
        msg: "{{ ansible_python.interpreter }}"
        
    - name: Test jmespath import
      command: "{{ ansible_python.interpreter }} -c 'import jmespath; print(jmespath.__file__)'"
      register: jmespath_test
      
    - name: Show jmespath location
      debug:
        var: jmespath_test.stdout

If you continue having issues, consider using the native json filter with map:


loop: "{{ data.list1 | map(attribute='name') | list }}"

After applying fixes, test with this simple playbook:


---
- name: Test jmespath functionality
  hosts: localhost
  vars:
    test_data:
      - {name: item1, value: 10}
      - {name: item2, value: 20}
  tasks:
    - name: Test json_query
      debug:
        msg: "{{ test_data | json_query('[].name') }}"