Fix Ansible Error: /usr/bin/python: not found on Remote Host

beginner๐Ÿ”ง Ansible2026-03-26| Ansible 2.8+, Ubuntu 20.04/22.04, Debian 11/12, Rocky Linux 8/9, AlmaLinux โ€” remote hosts without Python 2 installed

Error Message

fatal: [192.168.1.10]: FAILED! => {"changed": false, "msg": "/usr/bin/python: not found", "rc": 127}
#python#ansible_python_interpreter#interpreter#python3

The Error

Your playbook dies on the very first task, before it does anything useful:

fatal: [192.168.1.10]: FAILED! => {"changed": false, "msg": "/usr/bin/python: not found", "rc": 127}

Ansible tried to run /usr/bin/python on the remote host. That path doesn't exist. It's a one-line failure that catches a lot of people upgrading to Ubuntu 20.04 or Debian 11 โ€” those distros ship Python 3 only, and /usr/bin/python (Python 2's home) is just gone.

Why This Happens

Ansible needs Python on the remote host to execute modules. Before version 2.12, it defaulted to /usr/bin/python โ€” a Python 2 path. Ubuntu 18.04 and older had both Python 2 and Python 3, so this worked fine. Ubuntu 20.04 dropped Python 2 entirely. Same story with Debian 11, Rocky Linux 8, and AlmaLinux 8.

Two things can trigger this:

  • The remote host has Python 3 at /usr/bin/python3, but no /usr/bin/python symlink.
  • Your ansible.cfg or inventory explicitly sets ansible_python_interpreter=/usr/bin/python.

Quick Fix โ€” Set ansible_python_interpreter

Point Ansible at the right Python binary. That's all it takes.

Option 1: Per-host or per-group in your inventory

Add ansible_python_interpreter directly to the affected host or group:

[webservers]
192.168.1.10 ansible_python_interpreter=/usr/bin/python3
192.168.1.11 ansible_python_interpreter=/usr/bin/python3

Prefer group vars? Use this instead:

[webservers:vars]
ansible_python_interpreter=/usr/bin/python3

Option 2: Auto-discovery (best for mixed environments)

Set the interpreter to auto and let Ansible figure it out:

[webservers:vars]
ansible_python_interpreter=auto

With auto, Ansible SSHes into each host, checks which Python versions are available, and picks the best one. No manual configuration per host. Works well when your fleet is a mix โ€” some hosts still on Python 2, most already on Python 3.

Permanent Fix โ€” ansible.cfg

Setting it per-inventory gets old fast. The cleaner approach: add a global default to ansible.cfg:

[defaults]
interpreter_python = auto_silent

auto_silent does the same auto-detection as auto, minus the deprecation warning. That warning clutters output in CI/CD pipelines โ€” silence it early.

All your hosts on Python 3? Skip the auto-detection overhead and be explicit:

[defaults]
interpreter_python = /usr/bin/python3

Alternative: Install python-is-python3 on the Remote Host

Sometimes you can't touch Ansible's config โ€” maybe it's a shared ansible.cfg, or you're running legacy playbooks with hardcoded paths. In that case, create the symlink on the remote host instead:

# Ubuntu / Debian
sudo apt install python-is-python3 -y

# Verify the symlink
ls -la /usr/bin/python
# /usr/bin/python -> /usr/bin/python3

This package creates the /usr/bin/python โ†’ /usr/bin/python3 symlink. Old playbooks keep working without any Ansible config changes.

Verify the Fix

Run a quick ping to confirm Ansible can reach the host and execute:

ansible 192.168.1.10 -m ping -i inventory.ini

You want to see this:

192.168.1.10 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Want to double-check which interpreter Ansible actually picked? Run:

ansible 192.168.1.10 -m command -a "python3 --version" -i inventory.ini

For full visibility during a playbook run, add -v:

ansible-playbook site.yml -i inventory.ini -v

Look for this line in the output:

Using /usr/bin/python3 as the Python interpreter on host 192.168.1.10

Summary

  • Ansible defaults to /usr/bin/python, which doesn't exist on Python 3-only hosts (Ubuntu 20.04+, Debian 11+, Rocky Linux 8+).
  • Fastest fix: add ansible_python_interpreter=/usr/bin/python3 to your inventory.
  • Best long-term fix: set interpreter_python = auto_silent in ansible.cfg.
  • Confirm it works: ansible <host> -m ping.

Related Error Notes