Ansible Error Guide: 'value of state must be one of' — Fix Invalid Module Argument Choices
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.
- #ansible
- #automation
- #troubleshooting
- #errors
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.
enabledis valid forsystemd’senabled:but not itsstate:). - 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/truepassed 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: enabledvsenabled: true). - Typo or casing —
state: Presentorstate: instaled. - Templated value resolving wrong —
state: "{{ desired }}"wheredesiredis undefined, empty, or a boolean. - Boolean where a string choice is required — YAML turning
state: yesintoTrue. - 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 exactchoicesbefore 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 —
statevsenabled,statevsstatus— 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.
More Ansible prompts & error guides
Every Ansible AI prompt and troubleshooting guide, in one place.
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.