Ansible Error Guide: 'Specified hosts and/or --limit does not match any hosts' — Fix Targeting
Fix Ansible's 'Specified hosts and/or --limit does not match any hosts' error: correct the inventory source, host patterns, group names, and --limit so your play targets the hosts you expect.
- #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 prints this when the combination of the play’s hosts: pattern, the loaded inventory, and any --limit on the command line resolves to zero hosts. The run stops immediately without touching anything:
[WARNING]: Could not match supplied host pattern, ignoring: web
ERROR! Specified hosts and/or --limit does not match any hosts
A closely related message means Ansible loaded an inventory but it contained no usable hosts at all:
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
Both point to the same class of problem: the targeting math produced an empty set. This is a safety stop — it is far better than the silent-success trap where --limit typo matches nothing and exits 0.
Symptoms
- The play errors out before the first task, naming
--limitor the host pattern. - A
[WARNING] Could not match supplied host pattern, ignoring:line precedes the error, naming the exact pattern that missed. provided hosts list is empty, only localhost is available— the inventory itself parsed to zero hosts.- The same playbook works from a teammate’s machine or another directory but not yours.
ansible-inventory --listshows hosts, yet--limit somegroupstill matches nothing.
Common Root Causes
- Wrong or missing inventory source: no
-i, noinventory =inansible.cfg, and the default/etc/ansible/hostsis empty — so only implicit localhost exists. - Host pattern doesn’t match inventory names: the play says
hosts: webbut the inventory group iswebservers, or hosts are listed by IP and you targeted by name. --limitintersects to empty:--limit stagingwherestagingisn’t a group, or--limit web01:&stagingwhereweb01isn’t instaging.- Dynamic inventory returned nothing: a cloud inventory plugin with a filter that matched no instances, or expired credentials returning an empty list.
- Group exists but has no members: a parent group defined with no hosts and no populated children.
- Trailing typo or comma:
--limit "web01,"or a pattern with a stray space that Ansible can’t match. - Running from the wrong directory: a relative
inventorypath inansible.cfgthat only resolves inside the project root.
Diagnostic Workflow
First, ask Ansible which inventory it is actually loading and what hosts it sees — most of these bugs are an inventory-source problem, not a pattern problem:
ansible-inventory -i inventory/ --list --yaml
ansible-inventory -i inventory/ --graph
Then test the exact pattern the play (or your --limit) uses, without running anything, using --list-hosts:
ansible-playbook site.yml -i inventory/ --limit staging --list-hosts
ansible web --list-hosts -i inventory/ # ad-hoc pattern check
Confirm which config and inventory path are in effect, since a stale ansible.cfg is a frequent culprit:
ansible --version # shows the config file in use
ansible-config dump --only-changed | grep -i inventory
Reproduce and verify the fix with a minimal play that just lists hosts:
- name: Verify targeting resolves
hosts: webservers # match the real group name from --graph
gather_facts: false
tasks:
- name: Show which hosts matched
ansible.builtin.debug:
msg: "Running on {{ inventory_hostname }}"
ansible-playbook verify.yml -i inventory/ --limit staging --list-hosts
Example Root Cause Analysis
An engineer ran ansible-playbook deploy.yml --limit web and got Could not match supplied host pattern, ignoring: web followed by the error. The playbook’s own hosts: line was hosts: all, so the problem had to be the --limit.
Running ansible-inventory -i inventory/ --graph showed the groups were webservers, dbservers, and loadbalancers — there was no group or host literally named web. The --limit web intersected with all to produce the empty set, and Ansible correctly refused to run rather than silently do nothing.
The immediate fix was --limit webservers. To make the mistake self-evident next time, the team standardized on running --list-hosts as a pre-check in their deploy wrapper, so an empty match is caught and printed before the real command. They also added an alias group so both web and webservers resolve, removing the naming ambiguity that caused the miss.
Prevention Best Practices
- Always pass an explicit
-ior setinventory =in a project-localansible.cfg, so you never accidentally fall back to an empty/etc/ansible/hosts. - Run
--list-hostsbefore every real run in scripts and CI; treat an empty result as a hard failure, not a no-op. - Keep group and host names consistent with what your playbooks reference; use
ansible-inventory --graphin review to confirm names. - For dynamic inventory, validate the plugin output (
ansible-inventory --list) as a CI step so an empty cloud result fails loudly instead of at deploy time. - Avoid trailing commas and stray spaces in
--limit; quote patterns that contain:,&, or!. - Commit the
ansible.cfgwith the project so the inventory path resolves the same way for everyone.
Quick Command Reference
# See the effective config file and inventory setting
ansible --version
ansible-config dump --only-changed | grep -i inventory
# Dump and visualize the loaded inventory
ansible-inventory -i inventory/ --list --yaml
ansible-inventory -i inventory/ --graph
# Dry-run the targeting without executing tasks
ansible-playbook site.yml -i inventory/ --limit staging --list-hosts
# Check an ad-hoc pattern
ansible 'webservers:&staging' -i inventory/ --list-hosts
Conclusion
“Specified hosts and/or —limit does not match any hosts” is Ansible refusing to run against an empty target set — a safety feature, not a bug in your playbook logic. Confirm the inventory is actually loaded with ansible-inventory --graph, check the exact pattern with --list-hosts, and reconcile the play’s hosts: value and your --limit against the real group names. Bake --list-hosts into your run scripts so an empty match is always caught before, not after, you expect a change to happen.
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.