Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Ansible By James Joyner IV · · 8 min read

Ansible Error Guide: 'does not support check mode' — Fix Check-Mode Task Failures

Quick answer

Fix Ansible's 'does not support check mode' error using check_mode false, changed_when, and idempotent modules so --check dry-runs report changes honestly.

Part of the Ansible Playbook & Module Errors hub
  • #ansible
  • #automation
  • #troubleshooting
  • #errors
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

When you run a play with --check, Ansible skips or flags any task whose module cannot simulate its action. Depending on module and version you will see one of these:

fatal: [app01]: FAILED! => {"changed": false, "msg": "remote module (command) does not support check mode"}

Or, more commonly, a skip notice in the output:

skipping: [app01] => (item=...)  # module does not support check mode, skipping task

This is not a broken host or a bad argument — it is Ansible telling you that in dry-run mode it cannot safely predict what this task would do, so it refuses to run or skips it rather than pretend.

Symptoms

  • Running ansible-playbook --check reports a task as failed or skipped with a check-mode message.
  • command, shell, raw, and script tasks are the usual culprits, since Ansible cannot know what an arbitrary command would do.
  • A --check run reports changed=0 for a play you know would change things, because change-detecting tasks were skipped.
  • The play runs fine without --check but cannot be dry-run for review.
  • A downstream task fails in check mode because a variable it depended on was registered by a skipped task.

Common Root Causes

  • Arbitrary-command modulescommand/shell/raw/script have no way to simulate side effects, so they do not support check mode by default.
  • Read-only tasks skipped unnecessarily — a command that only gathers information is skipped in check mode even though it is safe to run.
  • Custom module without check-mode support — a module written with supports_check_mode=False.
  • Registered variable never set — a fact-gathering task skipped in check mode leaves a register variable undefined for later tasks.
  • Expecting a full dry-run from modules that cannot provide one — treating --check as a guarantee every task simulates cleanly.

Diagnostic Workflow

Run the play in check mode with diff to see which tasks are skipped versus simulated:

ansible-playbook -i inventory site.yml --check --diff

For a read-only command that is safe to run even in check mode, force it to execute with check_mode: false:

- name: Read current app version (safe in check mode)
  ansible.builtin.command: /usr/local/bin/app --version
  register: app_version
  check_mode: false          # this command has no side effects; always run it
  changed_when: false        # reading a version never counts as a change

For a command that does change state, make its change reporting honest so --check output is meaningful:

- name: Apply migration (mutating command)
  ansible.builtin.command: /usr/local/bin/migrate --apply
  register: migrate_out
  changed_when: "'applied' in migrate_out.stdout"

Verify a custom module’s declared support:

ansible-doc my_namespace.my_collection.my_module | grep -i 'check_mode\|check mode'

Example Root Cause Analysis

A team adopted --check for change-review before every production run. The dry-run reported changed=0 and, trusting it, they promoted the change — which then made dozens of changes when applied for real. Investigating, --check --diff showed the config-detection tasks were all command tasks that check mode had skipped, so nothing downstream ran and the play appeared inert.

The fix reshaped the read-only tasks: every information-gathering command got check_mode: false and changed_when: false so it ran and reported no change in dry-run, and the genuinely mutating commands got accurate changed_when expressions so their potential change showed up in check mode. Where possible, command tasks were replaced with idempotent built-in modules that natively support check mode. After that, a --check run reflected reality and the review step became trustworthy again.

Prevention Best Practices

  • Prefer idempotent built-in modules (copy, template, file, package, service) over command/shell; they support check mode natively.
  • Add check_mode: false and changed_when: false to read-only command tasks so they run safely and report no change during dry-runs.
  • Give mutating command tasks accurate changed_when expressions so --check output reflects real potential changes.
  • Set supports_check_mode=True in custom modules and honor module.check_mode inside them.
  • Do not treat --check as a guarantee of full simulation; verify with --check --diff which tasks actually run.

Quick Command Reference

# Dry-run with diffs to see what would change
ansible-playbook -i inventory site.yml --check --diff

# Run a single play in check mode
ansible-playbook -i inventory site.yml --check --limit <host>

# Inspect a module's check-mode support
ansible-doc <module> | grep -i 'check'

# Force a safe read-only task to run in check mode (in YAML)
# check_mode: false  +  changed_when: false

Conclusion

“does not support check mode” means Ansible will not guess what an arbitrary command would do during a dry-run, so it skips or fails the task rather than lie. Make read-only commands run with check_mode: false and changed_when: false, give mutating commands honest change detection, and prefer idempotent modules that simulate natively. Done right, --check becomes a review you can trust instead of a green light that hides real changes.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.