Your playbook executes, the module runs, and then crashes with a cryptic error message about module failure. The error message might mention module_stderr, msg, or just a raw Python exception. Module failures are among the most diverse Ansible errors because each module can fail in unique ways.
Let's break down how to systematically diagnose and fix module failures.
Understanding the Error
Module failures come in many forms:
fatal: [webserver01]: FAILED! => {"msg": "The module failed to execute correctly, you probably need to install the python module on the host."}Or with Python traceback:
fatal: [webserver01]: FAILED! => {
"module_stdout": "",
"module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_apt_payload_abc123\", line 25, in <module>\n import apt\nModuleNotFoundError: No module named 'apt'",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}The module_stderr contains the actual Python error, which tells you exactly what went wrong.
Step 1: Check the Full Error Output
Always run with verbose output to see the complete error:
ansible-playbook -i inventory deploy.yml -vvvLook for module_stderr in the output. Common Python errors:
ImportError/ModuleNotFoundError:
``
ModuleNotFoundError: No module named 'requests'
``
Missing Python dependency.
PermissionError:
``
PermissionError: [Errno 13] Permission denied: '/etc/nginx/nginx.conf'
``
File permissions issue.
SyntaxError:
``
SyntaxError: invalid syntax
``
Python version mismatch.
Step 2: Verify Python Version Compatibility
Ansible modules require specific Python versions. Check what's on the target:
ansible webserver01 -i inventory -m shell -a "python3 --version"
ansible webserver01 -i inventory -m shell -a "python --version"Ansible 2.12+ requires Python 3.8+ on target hosts. Older targets need specific configuration:
# In inventory
all:
hosts:
legacyhost:
ansible_python_interpreter: /usr/bin/python2.7Check Ansible's detected interpreter:
ansible webserver01 -i inventory -m setup -a "filter=ansible_python*"Step 3: Install Missing Python Dependencies
Many modules need Python libraries. For common modules:
apt module:
``bash
# On Debian/Ubuntu targets
ansible webserver01 -i inventory -b -m raw -a "apt-get update && apt-get install -y python3-apt"
yum/dnf module:
``bash
# On RHEL/CentOS targets
ansible webserver01 -i inventory -b -m raw -a "yum install -y python3-dnf"
docker_container module:
``bash
ansible webserver01 -i inventory -b -m pip -a "name=docker"
kubernetes module:
``bash
ansible webserver01 -i inventory -b -m pip -a "name=kubernetes"
For a systematic approach, create a requirements file:
- name: Install Python dependencies
hosts: all
become: yes
tasks:
- name: Install pip packages
pip:
name:
- requests
- docker
- boto3
state: presentStep 4: Handle Module-Specific Issues
Different modules have unique failure modes.
apt module failures:
- name: Install package
apt:
name: nginx
state: presentCommon errors and fixes:
```yaml # If apt cache is stale - name: Update apt cache apt: update_cache: yes cache_valid_time: 3600
# If dpkg is locked - name: Wait for dpkg lock shell: while fuser /var/lib/dpkg/lock >/dev/null 2>&1; do sleep 5; done changed_when: false
# If package has unmet dependencies - name: Fix broken packages shell: apt-get -f install -y become: yes ```
yum/dnf module failures:
# If yum is locked
- name: Wait for yum lock
shell: while [ -f /var/run/yum.pid ]; do sleep 5; done
changed_when: falsecopy/template module failures:
# Permission denied
- name: Copy file with proper permissions
copy:
src: files/app.conf
dest: /etc/app/app.conf
owner: app
group: app
mode: '0644'
become: yessystemd module failures:
```yaml # systemd not running - name: Check systemd command: systemctl is-system-running register: systemd_status failed_when: false changed_when: false
- name: Start service
- systemd:
- name: nginx
- state: started
- when: systemd_status.rc == 0
`
Step 5: Debug with Ansible Debug
Use the debug module to inspect variables before modules use them:
```yaml - name: Debug before module debug: var: my_variable
- name: Use module
- some_module:
- param: "{{ my_variable }}"
`
For complex module failures, enable Python debugging:
ANSIBLE_DEBUG=True ansible-playbook -i inventory deploy.yml 2>&1 | grep -A 20 "module_failure"Step 6: Handle File Permission Issues
Many module failures are permission-related. The error typically shows:
PermissionError: [Errno 13] Permission denied: '/path/to/file'Fix by ensuring proper ownership:
- name: Create directory with permissions
file:
path: /opt/app
state: directory
owner: app
group: app
mode: '0755'
become: yesOr run the entire play with elevated privileges:
- name: Configure application
hosts: all
become: yes
tasks:
- name: Copy config
copy:
src: app.conf
dest: /etc/app/app.conf
owner: root
group: root
mode: '0644'Step 7: Fix Module Path Issues
Sometimes Ansible can't find custom modules:
fatal: [webserver01]: FAILED! => {"msg": "The module my_custom_module was not found in configured module paths"}Check your module path configuration:
ansible-config dump | grep MODULESAdd custom module paths in ansible.cfg:
[defaults]
library = ./modules:/usr/share/ansible/modulesStep 8: Handle Asynchronous Task Failures
Async tasks fail differently:
```yaml - name: Long running task command: /opt/app/long-install.sh async: 3600 poll: 0 register: install_job
- name: Check async status
- async_status:
- jid: "{{ install_job.ansible_job_id }}"
- register: job_result
- until: job_result.finished
- retries: 60
- delay: 60
`
If async fails silently, check the job status:
- name: Check async result
debug:
var: job_resultStep 9: Test Modules Isolated
Run modules directly with ad-hoc commands:
```bash # Test apt module ansible webserver01 -i inventory -b -m apt -a "name=nginx state=present"
# Test copy module ansible webserver01 -i inventory -b -m copy -a "src=/local/file dest=/remote/path"
# Test systemd module ansible webserver01 -i inventory -b -m systemd -a "name=nginx state=started" ```
This isolates the module from playbook complexity.
Step 10: Handle Deprecated Module Parameters
Old playbooks might use deprecated parameters:
[DEPRECATION WARNING]: The 'validate_certs' parameter is deprecated, use 'validate_certs' instead.Check module documentation:
ansible-doc aptUpdate to current parameters:
```yaml # Old (deprecated) - name: Install package apt: name: nginx update_cache: yes # Old parameter
# New (correct) - name: Install package apt: name: nginx update_cache: true # Boolean not string cache_valid_time: 3600 ```
Step 11: Fix JSON Output Parsing
Modules return JSON, and parsing failures look like:
fatal: [webserver01]: FAILED! => {"msg": "Error parsing JSON output: Expecting value: line 1 column 1 (char 0)"}This usually means the module crashed before returning JSON. Check what it actually returned:
ansible webserver01 -i inventory -m your_module -a "args" -vvv 2>&1 | grep module_stdoutThe module_stdout contains what the module printed before crashing.
Quick Verification
Test module functionality:
```bash # Basic module test ansible all -i inventory -m ping
# Gather facts to test setup module ansible all -i inventory -m setup --tree /tmp/facts
# Test specific module with check mode ansible all -i inventory -b -m apt -a "name=nginx state=present" --check ```
Prevention Best Practices
- 1.Always install Python dependencies before using modules:
```yaml - name: Prepare Python environment hosts: all become: yes tasks: - name: Install pip package: name: python3-pip state: present
- name: Install required packages
- pip:
- name:
- - requests
- - docker
- state: present
`
- 1.Use virtual environments for complex dependencies:
- name: Create virtualenv
pip:
name: docker
virtualenv: /opt/venv
virtualenv_python: python3- 1.Validate module parameters with
ansible-doc:
ansible-doc <module_name>Module failures require reading the actual Python error. The verbose output tells you exactly what failed. Start with the traceback, fix the underlying issue (missing package, wrong permissions, version mismatch), and test with ad-hoc commands before running full playbooks.