What's Happening
You run a playbook and Ansible prints:
[WARNING]: Could not match supplied host pattern, ignoring: webservers
[WARNING]: No hosts matched, nothing to do
The playbook exits immediately without touching a single task. Ansible found your inventory file โ it just couldn't locate the host group or hostname referenced in the playbook's hosts: field.
Almost every time, it's a name mismatch: a typo, the wrong inventory path, or a structural problem in the inventory file. Usually a 2-minute fix once you know where to look.
Debug Process
Step 1 โ List what Ansible actually sees in inventory
Start here. Ask Ansible to enumerate every host and group it can parse from your inventory:
# Using a specific inventory file
ansible-inventory -i inventory.ini --list
# Or if you use a directory
ansible-inventory -i inventories/production --list
Scan the JSON output. If webservers (or whatever group you referenced) is absent, Ansible genuinely cannot find it. Either the file itself has a problem, or you're pointing at the wrong file entirely.
Prefer a human-readable tree? Use --graph:
ansible-inventory -i inventory.ini --graph
A healthy group looks like this:
@all:
|--@webservers:
| |--web01.example.com
| |--web02.example.com
|--@ungrouped:
Step 2 โ Check what your playbook references
Open your playbook and find the hosts: line:
---
- name: Deploy web app
hosts: webservers
tasks:
...
That value must exactly match a group name or hostname in inventory. Case-sensitive. No spaces. Go character by character if you have to โ a single letter off will cause this error.
Step 3 โ Confirm you're pointing at the right inventory file
The single most common cause: running the playbook without -i, so Ansible silently falls back to /etc/ansible/hosts. That file is usually empty, or it doesn't contain your groups.
# Wrong โ uses default /etc/ansible/hosts
ansible-playbook deploy.yml
# Correct โ explicitly specify your inventory
ansible-playbook -i inventory.ini deploy.yml
ansible-playbook -i inventories/production deploy.yml
To avoid repeating -i on every command, set the path once in ansible.cfg:
[defaults]
inventory = ./inventory.ini
Solution
Fix 1 โ Correct the inventory file structure
A valid INI inventory with a [webservers] group looks like this:
[webservers]
web01.example.com
web02.example.com ansible_user=ubuntu
[dbservers]
db01.example.com ansible_user=centos ansible_port=22
Four mistakes that silently break group matching:
- Extra spaces inside brackets:
[ webservers ]โ Ansible treats this as a different string, not the groupwebservers - Typo:
[webserver]in inventory vs.hosts: webserversin the playbook - Hosts listed before their group header โ they land in
[ungrouped]instead - YAML inventory syntax accidentally used inside an
.inifile (or vice versa)
Prefer YAML inventory? The equivalent structure:
all:
children:
webservers:
hosts:
web01.example.com:
web02.example.com:
ansible_user: ubuntu
dbservers:
hosts:
db01.example.com:
ansible_user: centos
Fix 2 โ Match the hosts pattern exactly
Update the playbook to use a pattern that actually exists in inventory:
---
- name: Deploy web app
hosts: webservers # must match exactly
become: true
tasks:
- name: Install nginx
apt:
name: nginx
state: present
Ansible supports several pattern forms for targeting multiple groups at once:
hosts: all # every host in inventory
hosts: webservers,dbservers # multiple groups
hosts: webservers:&staging # intersection (webservers AND staging)
hosts: webservers:!dbservers # webservers but NOT dbservers
Fix 3 โ Add inventory path to ansible.cfg
Drop a project-level ansible.cfg next to your playbook and forget about -i forever:
[defaults]
inventory = ./inventory.ini
remote_user = ubuntu
host_key_checking = False
Ansible picks up ansible.cfg from the current directory automatically. Running ansible-playbook deploy.yml without -i will now work correctly.
Verification
Three commands worth running before touching any server:
# Confirm the group now appears
ansible-inventory -i inventory.ini --graph
# Dry-run the playbook (no changes applied)
ansible-playbook -i inventory.ini deploy.yml --check
# List which hosts would be targeted
ansible-playbook -i inventory.ini deploy.yml --list-hosts
A successful --list-hosts run looks like this:
playbook: deploy.yml
play #1 (webservers): Deploy web app
pattern: ['webservers']
hosts (2):
web01.example.com
web02.example.com
Still seeing 0 hosts or the warning? Go back to Step 1.
Tips
Complex patterns like webservers:&production:!disabled are easy to get wrong, especially with larger inventories. Before putting a pattern in a playbook, I verify the logic with the Regex Tester on ToolCraft โ paste your host list, test whether the pattern matches what you expect. It runs entirely in the browser with no data uploaded, which matters when your list contains internal server names.
Lessons Learned
- Always pass
-iexplicitly when running from outside a project directory, or configureansible.cfgso inventory is always resolved correctly. - Run
ansible-inventory --graphfirst whenever a playbook behaves unexpectedly โ it shows exactly what Ansible parsed, not what you think you wrote. - INI group headers are whitespace-sensitive โ
[webservers]and[ webservers ]are different strings as far as Ansible is concerned. - Use
--list-hostsbefore every significant run โ a safe, read-only check that confirms your targeting before any task touches a real server.

