Introduction

Ansible callback plugins control how playbook output is displayed, logged, and reported. When callbacks are misconfigured, you may see no output at all, missing log entries, or notifications that never fire. This severely impacts debugging, compliance logging, and CI/CD integration. The issue is particularly common when migrating playbooks between environments, upgrading Ansible versions, or deploying custom callback plugins for enterprise reporting.

Unlike standard output, callback plugins operate at the Ansible engine level and must be properly loaded, whitelisted, and configured to function. A missing or misconfigured callback can silently fail with no error message, making diagnosis difficult.

Symptoms

Playbook runs with no visible output:

```bash $ ansible-playbook deploy.yml

# No output at all - screen stays blank for the entire execution # But the playbook completes successfully $ echo $? 0 ```

Expected log files are not created:

```bash $ ansible-playbook deploy.yml [Output shown on screen]

$ ls -la /var/log/ansible/ total 0 # No log files created despite callback configuration ```

Callback plugin errors in verbose mode:

bash
$ ansible-playbook deploy.yml -vvv
[WARNING]: callback plugin 'my_custom' not found in /usr/share/ansible/plugins/callback:/etc/ansible/callback_plugins
[WARNING]: Failed to load callback plugin 'json': No module named 'ansible.modules.callback.json'

Notification callbacks (Slack, email) not firing:

```yaml # ansible.cfg [defaults] callbacks_enabled = community.general.slack

# Playbook runs but no Slack notification sent # No error in output ```

Inconsistent output format despite configuration:

```bash $ grep stdout_callback ansible.cfg stdout_callback = yaml

$ ansible-playbook test.yml # Output is still in default format, not YAML TASK [Debug] *************** ok: [localhost] => { "msg": "test" } ```

Tower/AWX callback receiver errors:

bash
2024-04-09 10:15:23,456 ERROR awx.main.callbacks Callback receiver failed to process event
2024-04-09 10:15:23,789 WARNING awx.main.dispatch Job event dropped: callback plugin error

Common Causes

1. Callback Plugin Not Whitelisted

In Ansible 2.11+, callback plugins must be explicitly enabled:

```ini # Old configuration (deprecated) callback_whitelist = timer, mail

# New configuration callbacks_enabled = ansible.builtin.timer, ansible.builtin.mail ```

2. Incorrect Plugin Path

The callback plugin is not in any of Ansible's search paths:

```bash # Default search paths ~/.ansible/plugins/callback:/usr/share/ansible/plugins/callback:/etc/ansible/callback_plugins

# Custom plugin in different location /home/user/my_plugins/custom_callback.py ```

3. stdout_callback vs callbacks_enabled Confusion

stdout_callback controls screen output, while callbacks_enabled controls non-stdout callbacks:

ini
[defaults]
stdout_callback = yaml           # Controls screen output
callbacks_enabled = timer, mail  # Controls other callbacks (logging, notifications)

4. Plugin Dependencies Missing

Custom callbacks may require Python packages:

python
# custom_callback.py
import requests  # If requests not installed, plugin fails silently
import custom_module  # Module not in Python path

5. Ansible Version Incompatibility

Callback API changes between Ansible versions:

```python # Ansible 2.9 style from ansible.plugins.callback import CallbackBase

# Ansible 2.15+ may require different imports from ansible.plugins.callback import CallbackBase from ansible.module_utils.common.text.converters import to_text ```

6. Tower/AWX Callback Conflicts

Tower's awx_display callback conflicts with custom stdout callbacks:

ini
# Tower sets this automatically
stdout_callback = awx_display
# Your custom setting is ignored

Step-by-Step Fix

Step 1: Diagnose Callback Loading Issues

Identify which callbacks are loaded:

```bash # List all available callback plugins ansible-doc -t callback -l

# Check which callbacks are configured ansible-config dump | grep -i callback

# Check callback paths ansible-config dump | grep CALLBACK_PLUGINS

# Test specific callback ansible-doc -t callback ansible.builtin.yaml

# Check for callback errors with maximum verbosity ansible-playbook test.yml -vvvv 2>&1 | grep -i callback ```

Create a diagnostic playbook:

```yaml # test_callbacks.yml - name: Test callback plugin configuration hosts: localhost gather_facts: false tasks: - name: Display callback configuration debug: msg: - "stdout_callback: {{ lookup('config', 'STDOUT_CALLBACK') }}" - "callbacks_enabled: {{ lookup('config', 'CALLBACKS_ENABLED') }}" - "callback_plugins: {{ lookup('config', 'CALLBACK_PLUGINS') }}"

  • name: Test output
  • debug:
  • msg: "This should appear in YAML format if callback is working"
  • name: Test task timing
  • debug:
  • msg: "Timing info should appear at end if timer callback is working"
  • `

Step 2: Fix stdout_callback Configuration

Configure the output callback correctly:

```ini # ansible.cfg [defaults] # Set stdout callback for screen output stdout_callback = yaml

# For JSON output (useful for CI/CD) # stdout_callback = json

# For minimal output # stdout_callback = minimal

# For Ansible 2.11+, use FQCN # stdout_callback = ansible.builtin.yaml

# Enable additional callbacks (non-stdout) callbacks_enabled = ansible.builtin.timer, ansible.builtin.profile_tasks

# Set callback plugin path if using custom plugins callback_plugins = /opt/ansible/plugins/callback ```

Verify the configuration:

```bash # Test with a simple playbook ansible-playbook test_callbacks.yml

# Expected YAML output: # TASK [Display callback configuration] ******** # ok: [localhost] => # msg: # - stdout_callback: yaml # - callbacks_enabled: ['timer', 'profile_tasks'] ```

Step 3: Fix Custom Callback Plugin Loading

For custom callback plugins:

```bash # Create plugin directory mkdir -p /opt/ansible/plugins/callback

# Set the path in ansible.cfg cat >> ansible.cfg << 'EOF' [defaults] callback_plugins = /opt/ansible/plugins/callback EOF ```

Create a test custom callback:

```python # /opt/ansible/plugins/callback/test_callback.py from __future__ import absolute_import, division, print_function __metaclass__ = type

from ansible.plugins.callback import CallbackBase

class CallbackModule(CallbackBase): """ Test callback plugin for verifying callback loading. """ CALLBACK_VERSION = 2.0 CALLBACK_TYPE = 'stdout' CALLBACK_NAME = 'test_callback'

def v2_playbook_on_start(self, playbook): self._display.display("TEST CALLBACK: Playbook started - %s" % playbook._file_name)

def v2_playbook_on_task_start(self, task, is_conditional): self._display.display("TEST CALLBACK: Task starting - %s" % task.get_name())

def v2_runner_on_ok(self, result): self._display.display("TEST CALLBACK: Task OK on %s" % result._host.get_name())

def v2_playbook_on_stats(self, stats): self._display.display("TEST CALLBACK: Playbook complete") ```

Test the custom callback:

```bash # Enable the custom callback export ANSIBLE_STDOUT_CALLBACK=test_callback

# Or in ansible.cfg # stdout_callback = test_callback

# Run a test playbook ansible-playbook test_callbacks.yml

# Should see "TEST CALLBACK:" prefixed messages ```

Step 4: Fix Notification Callbacks

Configure Slack, email, and other notification callbacks:

```ini # ansible.cfg [defaults] # Enable notification callbacks callbacks_enabled = community.general.slack, community.general.mail

# Path to callback plugins callback_plugins = /opt/ansible/plugins/callback ```

For Slack callback, create configuration:

yaml
# Create a vars file for sensitive data
# group_vars/all/vault.yml (encrypted with ansible-vault)
slack_token: "xoxb-your-bot-token"
slack_channel: "#deployments"

```python # /opt/ansible/plugins/callback/slack_notification.py # Or use the built-in community.general.slack callback

# Configure via environment variables or ansible.cfg ```

```bash # Set Slack callback options via environment export ANSIBLE_CALLBACK_WHITELIST=community.general.slack export SLACK_CHANNEL="#deployments" export SLACK_TOKEN="xoxb-your-token"

# Test the callback ansible-playbook deploy.yml ```

Step 5: Fix Tower/AWX Callback Issues

For Tower/AWX environments where custom callbacks conflict:

yaml
# In your playbook, force callback settings
- name: Deploy with custom callback
  hosts: all
  environment:
    ANSIBLE_STDOUT_CALLBACK: yaml
    ANSIBLE_CALLBACKS_ENABLED: timer,profile_tasks
  tasks:
    - name: Deployment task
      debug:
        msg: "Deploying..."

Or configure at the Job Template level:

bash
# Via Tower API
curl -X PATCH -k -u admin:password \
  -H "Content-Type: application/json" \
  -d '{
    "extra_vars": "{\"ansible_stdout_callback\": \"yaml\"}"
  }' \
  https://tower.example.com/api/v2/job_templates/42/

Step 6: Debug Silent Callback Failures

Enable callback debugging:

```bash # Set debug environment variables export ANSIBLE_DEBUG=1 export ANSIBLE_VERBOSITY=4

# Run with full debugging ansible-playbook test.yml 2>&1 | tee debug.log

# Look for callback loading messages grep -i "callback" debug.log grep -i "loading plugin" debug.log

# Check for Python import errors grep -i "import|module|error" debug.log ```

Create a callback debugging script:

```bash #!/bin/bash # debug_callback.sh

echo "=== Ansible Configuration ===" ansible-config dump | grep -i callback

echo "" echo "=== Available Callback Plugins ===" ansible-doc -t callback -l

echo "" echo "=== Plugin Search Paths ===" python3 -c "from ansible.config.manager import ConfigManager; cm = ConfigManager(); print('\n'.join(cm.data.get_settings().get('callback_plugins', 'Not set')))"

echo "" echo "=== Testing Callback Load ===" python3 << 'EOF' import sys from ansible.plugins.loader import callback_loader

print("Attempting to load callback plugins...") for name in ['yaml', 'json', 'timer']: try: plugin = callback_loader.get(name) if plugin: print(f"SUCCESS: {name} loaded") else: print(f"FAILED: {name} returned None") except Exception as e: print(f"ERROR loading {name}: {e}") EOF ```

Step 7: Fix Python Path Issues

Ensure callback dependencies are available:

```bash # Check Python path Ansible uses ansible localhost -m debug -a "msg={{ ansible_python.executable }}"

# Check if required modules are available ansible localhost -m pip -a "name=requests state=present"

# For virtual environments source /opt/ansible/venv/bin/activate pip install requests

# Set Python interpreter for Ansible export ANSIBLE_PYTHON_INTERPRETER=/opt/ansible/venv/bin/python ```

Verification

Test that callbacks work correctly:

```bash # Test stdout callback ansible-playbook test.yml # Should see output in configured format (YAML, JSON, etc.)

# Test timer callback ansible-playbook test.yml # Should see timing summary at the end: # Playbook run took 0 days, 0 hours, 0 minutes, 5 seconds

# Test profile_tasks callback ANSIBLE_CALLBACKS_ENABLED=profile_tasks ansible-playbook test.yml # Should see task timing for each task

# Test JSON output ANSIBLE_STDOUT_CALLBACK=json ansible-playbook test.yml | jq '.plays[].tasks[].hosts.localhost' # Should parse as valid JSON

# Test custom callback ANSIBLE_STDOUT_CALLBACK=test_callback ansible-playbook test.yml # Should see custom callback output ```

For Tower/AWX:

```bash # Launch a job and check output format curl -X POST -k -u admin:password \ https://tower.example.com/api/v2/job_templates/42/launch/

# Check job events curl -k -u admin:password \ "https://tower.example.com/api/v2/jobs/12345/job_events/" | jq '.results[].event' ```

  • [ansible-playbook-undefined-variable-jinja2-strict-mode](/articles/ansible-playbook-undefined-variable-jinja2-strict-mode) - Variable issues in templates
  • [ansible-handler-not-triggered-notify-missing](/articles/ansible-handler-not-triggered-notify-missing) - Handler execution problems
  • [ansible-module-not-found-python-dependency](/articles/ansible-module-not-found-python-dependency) - Python module loading issues
  • [WordPress troubleshooting: Ansible Artifact Download Uses an Old Mi](ansible-artifact-download-uses-an-old-mirror-after-proxy-change)
  • [WordPress troubleshooting: Ansible Audit Trail Misses Events Under ](ansible-audit-trail-misses-events-under-burst-load)
  • [WordPress troubleshooting: Ansible Background Worker Gets Stuck in ](ansible-background-worker-stuck-in-a-retry-loop)
  • [WordPress troubleshooting: Ansible Backup Completes but Restore Fai](ansible-backup-completes-but-restore-fails-checksum-validation)
  • [WordPress troubleshooting: Ansible Batch Importer Duplicates Rows A](ansible-batch-importer-duplicates-rows-after-a-retry)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "WordPress troubleshooting: Ansible Callback Plugin Not Producing Ex", "description": "Learn how to fix Ansible Callback Plugin Not Producing Expected Output. Professional WordPress troubleshooting solutions with step-by-step guidance. WP error fix, WordPress optimization, WP security, WordPress performance.", "url": "https://www.fixwikihub.com/ansible-callback-plugin-output-missing", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-12-15T13:16:57.206Z", "dateModified": "2025-12-15T13:16:57.206Z" } </script>