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

Ansible Error Guide: 'value of state must be one of' — Fix Invalid Module Argument Choices

Quick answer

Fix Ansible's 'value of state must be one of' error by supplying a valid choice, fixing templated values, quoting booleans, and checking module documentation.

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

Ansible raises this when a module argument that only accepts a fixed set of choices is given a value outside that set:

fatal: [app01]: FAILED! => {"changed": false, "msg": "value of state must be one of: present, absent, started, stopped, restarted, reloaded, got: enabled"}

The message is precise: it lists the allowed values and shows exactly what you passed (got: enabled). This is argument validation happening before the module does any work, so nothing changed on the host — the task never ran its logic.

Symptoms

  • A task fails immediately with value of <arg> must be one of: ... got: <value>.
  • The value looks reasonable but belongs to a different module (e.g. enabled is valid for systemd’s enabled: but not its state:).
  • A templated value resolves to something unexpected — an empty string, a boolean, or a typo.
  • The play worked before a module was renamed/migrated to an FQCN with slightly different choices.
  • yes/no/true passed where a string choice was expected.

Common Root Causes

  • Wrong choice for the argument — passing a value that another argument or module accepts, not this one (the classic state: enabled vs enabled: true).
  • Typo or casingstate: Present or state: instaled.
  • Templated value resolving wrongstate: "{{ desired }}" where desired is undefined, empty, or a boolean.
  • Boolean where a string choice is required — YAML turning state: yes into True.
  • Module confusion — copying an argument from a different module whose choices differ.
  • Version drift — a module version that removed or renamed a choice you relied on.

Diagnostic Workflow

Read the module’s accepted choices straight from the docs on your control node:

ansible-doc ansible.builtin.systemd | grep -A6 -i 'state\|enabled'

If the value is templated, print what it actually resolves to before the failing task:

- name: Show resolved state value
  ansible.builtin.debug:
    msg: "state resolves to >>{{ svc_state | default('UNDEFINED') }}<<"

- name: Manage the service
  ansible.builtin.systemd:
    name: nginx
    state: "{{ svc_state }}"     # must be one of the allowed service states
    enabled: true                 # 'enabled' is a separate boolean argument

Run just the offending play with high verbosity to see the exact argument dictionary Ansible built:

ansible-playbook -i inventory service.yml --limit app01 -vvv

Reproduce the validation error deliberately to confirm the fix path:

ansible app01 -i inventory -b -m systemd -a "name=nginx state=enabled"
# msg: value of state must be one of: reloaded, restarted, started, stopped, got: enabled

Example Root Cause Analysis

A play that should have enabled and started a service failed with value of state must be one of: ... got: enabled. The task read state: enabled. The author had conflated two distinct systemd arguments: state: controls runtime (started, stopped, restarted, reloaded), while enabled: is a separate boolean controlling whether the unit starts at boot. enabled was never a valid state.

ansible-doc ansible.builtin.systemd made the two arguments’ separate roles clear. The fix was to set state: started and enabled: true as two arguments on the same task. Because argument validation runs before the module acts, the host was untouched by the failure, so no cleanup was needed — but the task had silently never been managing boot-time enablement at all until this was corrected, which is the kind of gap the error usefully exposes.

Prevention Best Practices

  • Consult ansible-doc <module> for the exact choices before using a constrained argument, rather than guessing from a similar module.
  • For templated choice values, add a debug (or an assertion) that confirms the resolved value is in the allowed set before the task runs.
  • Quote string choices (state: "present") so YAML never coerces them into booleans.
  • Distinguish separate arguments that sound related — state vs enabled, state vs status — instead of overloading one.
  • Pin collection versions so a module’s choice set does not shift under you between runs.

Quick Command Reference

# Show a module's arguments and their allowed choices
ansible-doc ansible.builtin.systemd

# Run the failing play with the built argument dict visible
ansible-playbook -i inventory play.yml --limit <host> -vvv

# Reproduce validation ad hoc
ansible <host> -i inv -b -m systemd -a "name=<svc> state=<value>"

# List available modules to confirm you have the right one
ansible-doc -l | grep -i <keyword>

Conclusion

“value of state must be one of” is Ansible protecting you: it caught an argument value outside the module’s allowed set before anything changed. Read the module docs for the real choices, keep related-but-separate arguments (like state and enabled) distinct, and validate templated values before they reach the module. The error is a spelling check for your module contract — fix the value to a listed choice and the task proceeds.

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.