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
Stuck on this Ansible error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
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.
Fixed it? Get 500 Ansible & 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.
Stuck on this? Start guided troubleshooting
Open an interactive diagnostic session with this error already loaded. Work a step-by-step plan, record what each check returns, land on a root cause, and export a clean incident summary — no account needed to start.
Did this fix your issue?
Solved it a different way?
Share the fix that worked for you — reviewed, then published to help the next engineer.
That looks like it may contain a secret (key, token, password, or connection string). Please remove it — a note with a detected secret can’t be published.
Thanks — that helps. Published notes appear after a quick review.
More Ansible prompts & error guides
Every Ansible AI prompt and troubleshooting guide, in one place.
Trending errors this week
The error guides other engineers are actually reading right now.
- 1mount: wrong fs type, bad option, bad superblock
- 2Docker 'failed to set up container networking': Fix the Bridge and IP Pool
- 3Docker 'failed to create shim task': How to Fix the containerd Runtime Error
- 4Transport endpoint is not connected
- 5modprobe: FATAL: Module not found
- 6mount: wrong fs type, bad option, bad superblock
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.