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:

bash
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:

bash
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:

bash
ansible-playbook -i inventory deploy.yml -vvv

Look 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:

bash
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:

yaml
# In inventory
all:
  hosts:
    legacyhost:
      ansible_python_interpreter: /usr/bin/python2.7

Check Ansible's detected interpreter:

bash
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:

yaml
- name: Install Python dependencies
  hosts: all
  become: yes
  tasks:
    - name: Install pip packages
      pip:
        name:
          - requests
          - docker
          - boto3
        state: present

Step 4: Handle Module-Specific Issues

Different modules have unique failure modes.

apt module failures:

yaml
- name: Install package
  apt:
    name: nginx
    state: present

Common 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:

yaml
# If yum is locked
- name: Wait for yum lock
  shell: while [ -f /var/run/yum.pid ]; do sleep 5; done
  changed_when: false

copy/template module failures:

yaml
# 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: yes

systemd 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:

bash
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:

bash
PermissionError: [Errno 13] Permission denied: '/path/to/file'

Fix by ensuring proper ownership:

yaml
- name: Create directory with permissions
  file:
    path: /opt/app
    state: directory
    owner: app
    group: app
    mode: '0755'
  become: yes

Or run the entire play with elevated privileges:

yaml
- 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:

bash
fatal: [webserver01]: FAILED! => {"msg": "The module my_custom_module was not found in configured module paths"}

Check your module path configuration:

bash
ansible-config dump | grep MODULES

Add custom module paths in ansible.cfg:

ini
[defaults]
library = ./modules:/usr/share/ansible/modules

Step 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:

yaml
- name: Check async result
  debug:
    var: job_result

Step 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:

bash
[DEPRECATION WARNING]: The 'validate_certs' parameter is deprecated, use 'validate_certs' instead.

Check module documentation:

bash
ansible-doc apt

Update 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:

bash
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:

bash
ansible webserver01 -i inventory -m your_module -a "args" -vvv 2>&1 | grep module_stdout

The 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. 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. 1.Use virtual environments for complex dependencies:
yaml
- name: Create virtualenv
  pip:
    name: docker
    virtualenv: /opt/venv
    virtualenv_python: python3
  1. 1.Validate module parameters with ansible-doc:
bash
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.