AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Ansible debug vs assert: When to Use Each Module

By Luca Berton · Published 2024-01-01 · Category: troubleshooting

Complete comparison of Ansible debug and assert modules. Learn when to use debug for inspecting variables and assert for validating conditions, with practical.

debug and assert are both used during development and troubleshooting, but they solve fundamentally different problems. debug shows you data. assert validates conditions and fails the play if they're not met.

Quick Comparison

Featuredebugassert
PurposeDisplay informationValidate conditions
Fails on falseNeverYes
Stops playbookNeverYes (unless ignore_errors)
OutputVariable values, messagesSuccess/failure + custom message
Use caseInspection, troubleshootingValidation, pre-flight checks
Production useRarely (remove after debugging)Always (keep as guardrails)

debug: Inspect and Display

Show a Variable

- name: Show server config
  ansible.builtin.debug:
    var: ansible_default_ipv4
# Output:
# ok: [web01] => {
#     "ansible_default_ipv4": {
#         "address": "10.0.1.10",
#         "interface": "eth0",
#         ...
#     }
# }

Show a Message

- name: Display deployment info
  ansible.builtin.debug:
    msg: "Deploying {{ app_name }} v{{ version }} to {{ inventory_hostname }}"

Control Verbosity

# Only shown with -v
- ansible.builtin.debug:
    msg: "Detailed config: {{ all_config }}"
    verbosity: 1

# Only shown with -vv
- ansible.builtin.debug:
    msg: "Full variable dump"
    verbosity: 2
    var: hostvars[inventory_hostname]

Common debug Patterns

# Debug registered output
- ansible.builtin.command: df -h /
  register: disk
- ansible.builtin.debug:
    var: disk.stdout_lines

# Debug loop items
- ansible.builtin.debug:
    msg: "Processing {{ item.name }} ({{ item.state }})"
  loop: "{{ services }}"

# Debug complex expressions
- ansible.builtin.debug:
    msg: "{{ users | selectattr('role', 'equalto', 'admin') | map(attribute='name') | list }}"

See also: Ansible debug Module: Print Variables & Messages (Complete Guide)

assert: Validate and Guard

Basic Assertion

- name: Validate required variables
  ansible.builtin.assert:
    that:
      - version is defined
      - version | length > 0
      - environment in ['staging', 'production']
    fail_msg: "Missing or invalid deploy parameters. Need: -e version=X.Y.Z -e environment=staging|production"
    success_msg: "Parameters validated: v{{ version }} → {{ environment }}"

Pre-Flight Checks

- name: Pre-flight validation
  ansible.builtin.assert:
    that:
      - ansible_distribution == "Ubuntu"
      - ansible_distribution_major_version | int >= 22
      - ansible_memtotal_mb >= 2048
      - ansible_processor_vcpus >= 2
    fail_msg: >-
      Host {{ inventory_hostname }} doesn't meet requirements:
      Need Ubuntu 22+, 2GB RAM, 2 CPUs.
      Got {{ ansible_distribution }} {{ ansible_distribution_version }},
      {{ ansible_memtotal_mb }}MB RAM, {{ ansible_processor_vcpus }} CPUs.

Validate Task Output

- name: Check service health
  ansible.builtin.uri:
    url: "http://localhost:8080/health"
  register: health

- name: Verify service is healthy
  ansible.builtin.assert:
    that:
      - health.status == 200
      - health.json.status == "UP"
      - health.json.database == "connected"
    fail_msg: "Health check failed: {{ health.json | default('no response') }}"

Quiet Mode

# Don't show individual assertion results (cleaner output)
- name: Validate config
  ansible.builtin.assert:
    that:
      - db_host is defined
      - db_port | int > 0
      - db_name | length > 0
    quiet: true    # Only shows if assertion fails

When to Use Each

Use debug When

# Troubleshooting — "what does this variable contain?"
- ansible.builtin.debug:
    var: result

# Development — "is my filter working?"
- ansible.builtin.debug:
    msg: "{{ data | json_query('servers[?state==`running`].name') }}"

# Logging — "what happened during this run?"
- ansible.builtin.debug:
    msg: "Deployed {{ version }} at {{ ansible_date_time.iso8601 }}"

Use assert When

# Validation — "fail fast if requirements aren't met"
- ansible.builtin.assert:
    that: ansible_os_family == "Debian"
    fail_msg: "This playbook only supports Debian-based systems"

# Guardrails — "prevent dangerous operations"
- ansible.builtin.assert:
    that: environment != "production" or deploy_approved | default(false) | bool
    fail_msg: "Production deploys require -e deploy_approved=true"

# Post-conditions — "verify the task did what we expected"
- ansible.builtin.assert:
    that: migration_result.stdout is search("Successfully migrated")

See also: Ansible for Windows: Complete Guide to Windows Automation (2026)

Combined Pattern: Debug + Assert

# Show the data, then validate it
- name: Get service status
  ansible.builtin.uri:
    url: "http://{{ inventory_hostname }}:8080/status"
  register: status

- name: Show status (for troubleshooting)
  ansible.builtin.debug:
    var: status.json
    verbosity: 1    # Only in verbose mode

- name: Validate service is ready
  ansible.builtin.assert:
    that:
      - status.json.ready | bool
      - status.json.connections | int < status.json.max_connections | int
    fail_msg: "Service not ready on {{ inventory_hostname }}"

ansible-core 2.19 Note

In ansible-core 2.19, assert conditions must return actual booleans:

# ❌ BREAKS in 2.19 — truthy string, not boolean
- ansible.builtin.assert:
    that: inventory_hostname

# ✅ WORKS — explicit boolean
- ansible.builtin.assert:
    that: inventory_hostname | length > 0

See Ansible 12 Upgrade Guide for full details.

See also: Ansible assert Module: Validate Conditions and Fail Early (Complete Guide)

FAQ

Should I leave debug tasks in production playbooks?

Generally no. Remove debug tasks or set verbosity: 1 so they only appear with -v. Exception: important deploy summaries that serve as log entries.

Can assert be used as a dry-run validation?

Yes — assert is perfect for pre-flight checks. Run validation tasks at the start of your playbook to fail fast before making any changes. Combine with --check mode for comprehensive dry runs.

What happens when assert fails?

The task fails, and by default the playbook stops for that host. Use ignore_errors: true to continue (not recommended for critical validations), or any_errors_fatal: true to stop the entire play across all hosts.

Can I use assert in a loop?

Yes, but each assertion failure stops the loop. Use loop + assert for validating a list of conditions, or build a single that: list dynamically.

Conclusion

debug is your microscope — use it to inspect data during development and troubleshooting. assert is your guardrail — use it to validate conditions and fail fast when requirements aren't met. Keep debug temporary; keep assert permanent.

Category: troubleshooting

Browse all Ansible tutorials · AnsiblePilot Home