iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
Ansible’s loop keyword runs one task invocation for every element in a list. The current element is available as item unless you assign a different loop variable. Use loop for ordinary lists, shape complex data with Jinja filters such as flatten, product, and zip, and use until with retries and delay when each item must be retried until it succeeds.
The most common loop failures come from passing a string instead of a list, accidentally overwriting item in nested tasks, or assuming that a loop’s registered result has the same shape as a single task result. The examples below show the syntax, data-shaping patterns, migration rules, and diagnostics you need to avoid those problems.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsWhat an Ansible loop does
A loop attaches repetition to a task, not to an entire play. Ansible evaluates the task once for each value in the loop input, creating a separate task result for every value. In the default form, the current value is exposed through the variable item.
The loop keyword accepts a list. It does not accept a plain string, even when that string contains comma-separated values. If a lookup plugin might return a string, request a list explicitly with query() or with lookup(..., wantlist=True).
#1 Best Overall
- Powerful Turbo Fan:CAGIWIRU Electric Air Duster have reached speed up to 130000RPM,Can efficient remove dust and debris.With LED light and Three Adjustable Speed to meet with different cleaning tasks.
- With Attached USB C Fasting Charging cable.Charing 3 hours,Enjoy up to 240 minutes of use on the lowest setting, For third speed can use for 25mins.with four charging options to meet with your needs.
- Wide Application: attached 5 different nozzles,making it suitable for a variety of scenes, such as car,pet, pc, keyboards, and other electronic devices. It also serves for office and home clean duster.
- Handy Design & Portable:Cordless air duster electric nozzle is Light weight and small size, design and comfortable to hold and space saving, convenient to carry around. You can put it in your room or inside the car without taking up space.
- Economical &Reusable: Built durable materials with a long-lasting battery,our CAGIWIRU air duster it's a sustainable alternative to disposable air cans.
Ansible also supports older with_* loop forms and the until keyword. The modern loop form is usually clearer for ordinary iteration, while a specific with_* lookup can still be the most readable choice when the lookup itself is the point of the task.
Start with a basic list loop
This task installs three packages. Ansible invokes the package module three times, once with each package name.
- name: Ensure each package is installed
ansible.builtin.package:
name: '{{ item }}'
state: present
loop:
- nginx
- postgresql
- redis
Each iteration has the same module arguments except for item. Modules remain idempotent, so rerunning the playbook does not reinstall a package that is already present.
Loop over a variable containing dictionaries
Lists commonly contain records rather than scalar strings. Reference a field on the current record with dot notation or bracket notation.
- name: Create users
ansible.builtin.user:
name: '{{ item.name }}'
groups: '{{ item.groups }}'
state: present
loop: '{{ users }}'
The variable must resolve to a list, for example:
users:
- name: alice
groups: developers
- name: bob
groups: operators
If a record can omit a field, provide a default deliberately, such as {{ item.shell | default('/bin/bash') }}, rather than allowing an undefined-variable error to stop the play.
Guarantee that loop input is a list
Many “value is not a list” errors originate with lookup plugins. The result type depends on the lookup interface: ordinary lookup() may return a comma-separated string, whereas query() always returns a list.
Prefer query for lookup data
- name: Show every host in the all group
ansible.builtin.debug:
msg: '{{ item }}'
loop: '{{ query("inventory_hostnames", "all") }}'
The equivalent explicit list request is:
- name: Show every host in the all group
ansible.builtin.debug:
msg: '{{ item }}'
loop: '{{ lookup("inventory_hostnames", "all", wantlist=True) }}'
Use query() by default when the result is destined for loop. If you must use lookup(), add wantlist=True and verify the plugin supports that option.
Rank #2
- Screen Cleaner is Your Screen’s New Bestfriend! - EVEO is proud to present a screen cleaner that’s perfectly suited for your TV. Meet your new screen cleaner, computer screen cleaner, laptop cleaner, iPad cleaner, Macbook,tv cleaner or any other electronic device. Our screen cleaner spray and wipe along with the included plush microfiber cloth, easily removes dust, fingerprints & other smudges on the screen’s surface. Clean effectively for a streak-free screen
- Gentle on your Screens - Our screen cleaner spray and wipes is compatible to be used even for the most sensitive LCD, LED, CRT, and OLED screens in proper use. Be at ease knowing that this product is compatible with all the major brands: LG, SONY, Samsung, Sharp, iPad, iPhone, Android screens, Kindle, PC monitors - we’ve got you covered! Can be used as LCD screen cleaner, tv cleaner, smart tv screen cleaner, and more
- Premium Super Soft Plush Microfiber Cloth - Included in this efficient screen cleaning kit. This screen cleaner spray and wipe has our signature plush microfiber cloth specially designed to comply with screens and monitors and leave them streak-free. Has been shown to effectively absorbs stubborn stains, zero streaks, and no fiber shedding. Always use this together with our screen cleaner for the best results
- Easy-to-Use Screen Cleaner Kit + microfiber cleaning cloth - The EVEO Screen Cleaning Kit will easily be your new favorite tool when it comes to taking care of the things you love most, quick and easy solution for a streak-free screen. Simply screw on the sprayer gun on the screen cleaner bottle. Spray the cleaning liquid onto the microfiber cloth, then wipe the screen until desired cleanliness & shine is achieved.
- Quality Screen Care Kit Worth Purchasing - Enjoy a convenient Screen Cleaner anytime, anywhere you need it. Your satisfaction is our top priority. We stand behind the quality of our products and that’s why, you shouldn’t be worrying at all. We manufacture the Best Screen Cleaner. and can be used for laptop cleaning kit, laptop screen cleaner, tv screen cleaner for smart tv. MacBook screen cleaner, monitor cleaner or screen cleaner spray for electronic devices with microfiber cleaning cloth
Inspect the type before looping
When a variable comes from inventory, extra variables, or a role default, print it before adding a complex task:
- name: Inspect the value used by the loop
ansible.builtin.debug:
var: users
Ansible’s error normally identifies the offending expression. Check whether the value is undefined, a mapping, or a string. Convert or reshape it before the loop rather than hiding the error with a broad conditional.
Control variable names, labels, and indexes
loop_control manages how a loop is displayed and which variables it creates. A concise label keeps output readable when each record contains many fields.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- name: Show a concise label
ansible.builtin.debug:
msg: '{{ item.name }}'
loop: '{{ users }}'
loop_control:
label: '{{ item.name }}'
The label changes what Ansible prints for the iteration; it does not change the value passed to the task.
Use a descriptive loop variable
Rename item when the task is nested, when several records are in scope, or when a field named item would be confusing.
- name: Display each user with its index
ansible.builtin.debug:
msg: '{{ user_index }}: {{ user_record.name }}'
loop: '{{ users }}'
loop_control:
loop_var: user_record
index_var: user_index
index_var starts at zero. Use it for ordinal messages, deterministic names, or calculations that depend on position; do not treat it as a unique identifier when the list can be reordered.
Shape nested and related data with Jinja filters
Rather than writing deeply nested task loops, transform the input into the list that one task should consume. This keeps each task’s purpose visible and makes the loop variable predictable.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallRank #3
- 【Large size】:Measuring 800 x 300 mm/ 31. 5×12 inches, which is wider and taller than others. Large mouse pad can perfectly fit your keyboard and mouse of any size, and there is also ample space for peripherals such as phones, tablets, etc.
- 【LED backlight mouse pad】:Blade Hawks RGB mouse pad provides 7 static modes and 7 dynamic modes will give you the options you are looking for. Power-off memory function remembers the last lighting mode you selected. The super glow fiber Chroma will give you a colorful gaming setup that you want.
- 【Anti-slip rubber base】:Made from Natural rubber, this gaming mousepad will firmly grip your desktop, allowing you to enjoy the ultimate precision in the games you are most passionate about. It also comes with a texture that enhances this ability even further.
- 【Smooth and waterproof surface】: Micro-textured cloth surface, for extremely precise mouse control and a smooth movement. When liquid splashes on the gaming mouse pad, it forms water droplets and slides down. Will not delay your work or gameplay.
- 【Plug and play】: This mouse and keyboard pad is powered by USB, plug and play, no driver required. One button control light modes. Press one time to change the lighting mode, press twice to change the brightness, press and hold about 3 seconds turn ON/OFF.
Preserve with_items’ single-level flattening
The older with_items form flattens one nested list level implicitly. A direct conversion to loop does not reproduce that behavior. Add flatten(1) when the old shape relies on it:
- name: Process values from one nested level
ansible.builtin.debug:
msg: '{{ item }}'
loop: '{{ items | flatten(1) }}'
flatten(1) removes one level only. A deeper flatten can destroy meaningful grouping, so choose the depth intentionally.
Create a Cartesian product with product
Use product when every user must be paired with every database. Convert the product iterator to a list before passing it to the loop:
- name: Show every user and database pair
ansible.builtin.debug:
msg: 'user={{ item.0 }}, database={{ item.1 }}'
loop: '{{ users | product(databases) | list }}'
Each item is a two-element list. If you need named fields, set them in a preceding task or use a small transformation rather than relying on unexplained numeric positions.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Pair corresponding values with zip
zip combines values by position, so the first element of one list is paired with the first element of the other. Ensure the lists have the intended lengths before using the result:
- name: Pair names with ports
ansible.builtin.debug:
msg: '{{ item.0 }} listens on {{ item.1 }}'
loop: '{{ service_names | zip(service_ports) | list }}'
A zip operation does not express “every combination”; use product for that requirement.
Keep nested task loops from overwriting item
When a loop includes a task file, both the outer task and an inner task can otherwise use the default variable item. The inner loop then overwrites the outer value, producing warnings or incorrect parameters.
Rank #4
- 【Softer and More Comfortable】Vaydeer wrist rest has unique diamond pattern, which is the combination of softness and aesthetics. The materials of wrist rest are improved into higher quality memory foam and covered with silky smooth lycra. The computer wrist rest makes you as comfortable and cushiony as like rest your wrists on clouds.
- 【Ergonomic Wrist Saver】The wrist rests for keyboard and mouse comes with a 17.32×3.15×0.83 inch keyboard wrist pad and a 5.94×3.15×0.83 inch mouse wrist support. Based on ergonomic design, the unique concave shape is the perfect fit for your wrist joints. The wrist rest pad fits most computer keyboards and laptops, improve hand and wrist posture, release your wrist and arm stress.
- 【Non-Slip Rubber Bottom】Featuring an anti-skid silicone base on the bottom, this wrist keyboard support stays firmly in place on your desk, preventing the padding from sliding around, ensuring stable and consistent wrist support during extended computer sessions.
- 【Better Experience & Pain Relief】Our keyboard arm rest is beneficial to alleviate the soreness caused by direct contact and friction between your arm and a hard desk surface, reducing the risk of wrist fatigue or carpal tunnel. The soft texture of memory foam can evenly distribute the pressure around your wrists and provide good support with just enough give.
- 【Helpful in Multiple Scenarios】Whether you're working, studying, writing, typing, gaming, this keyboard and mouse rest combo is an essential accessory to add comfort and support to your hands and wrists. It’s also a great gift for men, women, family, friend, coworker, gamer, teacher, etc.
Assign a name to the outer variable with loop_control.loop_var:
- name: Run inner tasks for each application
ansible.builtin.include_tasks: inner.yml
loop: '{{ applications }}'
loop_control:
loop_var: outer_application
Inside inner.yml, the included tasks can use their own item safely while referring to the outer record as outer_application:
- name: Configure each port for the application
ansible.builtin.debug:
msg: '{{ outer_application.name }} uses port {{ item }}'
loop: '{{ outer_application.ports }}'
Name every outer loop when task inclusion or role composition creates another loop. This is safer than trying to copy the value after the inner task has already replaced it.
Retry each loop item with until
until reruns a task until its condition evaluates to true or the retry limit is exhausted. With retries and delay, it is suitable for transient service readiness, asynchronous API changes, or eventual consistency.
- name: Wait for the service to become active
ansible.builtin.command: systemctl is-active nginx
register: service_status
until: service_status.rc == 0
retries: 5
delay: 10
The condition is evaluated against the registered result from the current attempt. The current guide documents defaults of three retries and five seconds when until is present, but explicit values make timing predictable and self-documenting. Registered results include an attempts value.
Recommended Free Tools
Apply retries independently to loop items
When until and loop are on the same task, Ansible evaluates the retry condition for each item. One item can require several attempts while the next item starts only after that item succeeds or reaches its retry limit.
- name: Wait for each endpoint
ansible.builtin.uri:
url: '{{ item }}'
status_code: 200
register: endpoint_check
until: endpoint_check.status == 200
retries: 6
delay: 5
loop: '{{ endpoints }}'
Choose retry counts and delays based on the expected readiness window. A retry loop is not a substitute for fixing a deterministic failure such as a bad URL, missing permission, or invalid package name.
Best Value
- 【No Drill Mounted】Cable management tray can be assembled in as little as 3 minutes or less-simply. Side clips easily clampe the edge of desk, pass through the holes on the sides, and secure excess cables with baskets. Desk cable management supports inward or outward installation to meet your needs in different scenarios, and provides you with great convenience when collecting and organizing wires.
- 【Rubber Pad Protects Desk】Wire organizer under desk built-in soft rubber pads on the clamp protect your desk from scratches, so you will not damage your furniture or office.
- 【Sturdy and Beautiful】Cord management under desk is made of high-quality carbon steel and holds about 15 lbs. The wire basket has 2 holes on each side of the tray to enable your cables to pass freely. Cable baskets are suitable for desk thickness use from 0.4" to 2.4".
- 【Space Saving & Keep Organized】Desk cable management tray holds all your power cords, outlet strips, USB hubs and computer transformers hidden from your feet, and the data cables will not enter the vacuum cleaner to keep your desk clean and tidy. Desk wire organizer is also suitable for use in the kitchen and outdoors.
- 【Reduce Safety Risks】Cable tray under desk keeps all plugs away from your kids, no more worry about tripping. Using 2 holes wire tray saves extra space, helps you easily cabling and wire protection. The mesh design is not easy to accumulate dust, but avoids safety accidents caused by messy wires.
Process registered results from a loop
A task that uses register with a loop produces a result object containing a results list. Each element contains the loop value and the module’s result fields. A later task can loop over that collection.
- name: Check whether files exist
ansible.builtin.stat:
path: '{{ item }}'
loop: '{{ paths }}'
register: file_checks
- name: Report missing files
ansible.builtin.debug:
msg: '{{ item.item }} is missing'
when: not item.stat.exists
loop: '{{ file_checks.results }}'
In the second task, item is a result record, so the original path is at item.item. Module-specific fields such as stat.exists remain alongside it. Use a custom loop variable in the reporting task if the double item notation is hard to read.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Loop through inventory hosts
An inventory group is already a list of host names. The groups variable accesses a named group, while ansible_play_batch contains the hosts in the current play batch after serial batching is applied.
All hosts in an inventory group
- name: Show every inventory host
ansible.builtin.debug:
msg: '{{ item }}'
loop: '{{ groups["all"] }}'
Only hosts in the current batch
- name: Show hosts active in this batch
ansible.builtin.debug:
msg: '{{ item }}'
loop: '{{ ansible_play_batch }}'
Use query('inventory_hostnames', pattern) when you need a pattern-based inventory subset and want a list suitable for looping:
- name: Show database hosts
ansible.builtin.debug:
msg: '{{ item }}'
loop: '{{ query("inventory_hostnames", "databases:&production") }}'
Remember that a loop over host names only iterates data in the current task. It does not change the play’s target hosts.
Migrate from with_* to loop without changing behavior
Most older with_* forms can be replaced by loop, but migration is not always a text-only substitution. Compare the input type, lookup behavior, and flattening semantics before changing a mature playbook.
| Older form | Typical modern form | Important compatibility detail |
|---|---|---|
with_list |
loop |
Direct mapping when the input is already a flat list. |
with_items |
loop: '{{ values | flatten(1) }}' |
Preserve its implicit one-level flattening when nested values are possible. |
with_indexed_items |
flatten(1) plus loop_control.index_var |
Keep both the old flattening and the positional index. |
A lookup-specific form such as with_fileglob |
Often keep the with_* form |
A direct lookup form can be clearer than forcing an equivalent expression. |
After migration, run the playbook in a safe environment and inspect the rendered values. Pay particular attention to nested lists: a task may appear to succeed while processing a different number of elements after flattening behavior changes.
Diagnose common loop errors
“The value is not a list”
- Print the variable with
ansible.builtin.debugand confirm its type and shape. - Replace a lookup expression with
query(), or addwantlist=Truetolookup(). - Check that a YAML mapping was not supplied where a list of records was expected.
- Ensure a variable was not converted to a string by templating or by joining values earlier in the play.
Undefined variable or missing field
- Verify that the variable is defined for the host and execution path where the task runs.
- Check the field name and capitalization in dictionary records.
- Use
default()only when a missing value has a valid operational default. - For optional records, guard the task with a precise
whencondition instead of silently skipping malformed data.
The wrong value appears in a nested loop
- Give the outer loop a custom
loop_var. - Use that named variable in the included task file.
- Look for a role or included file that also assumes the default name
item.
Retries do not behave as expected
- Confirm that
untilreferences the registered variable from the same task. - Set
retriesanddelayexplicitly so the timing is visible. - Remember that retry evaluation is per loop item, not one global retry around the entire list.
- Run with
-vor-vvto inspect attempts and module output.
The migrated task processes too many or too few values
Compare the old with_items input with the new loop expression. Add flatten(1) only when the old task depended on one-level flattening; avoid unrestricted flattening that erases meaningful nesting.
Make loops predictable and maintainable
- Keep the loop input close to the task when it is short and static; use a named variable when the data is shared or generated.
- Use descriptive loop variables in included tasks and roles.
- Use labels to expose the identifying field without printing sensitive or bulky records.
- Shape data before the task instead of embedding complicated nested loops in module arguments.
- Use idempotent modules and stable keys so reruns converge on the same state.
- Validate list input early when a value comes from an external lookup or user-supplied variable.
- Use registered result collections deliberately: document when a later task expects
item.itemor another nested field. - Choose
untilfor transient conditions, not for masking configuration errors. - Increase command verbosity with
ansible-playbook -voransible-playbook -vvwhile diagnosing loop expansion and retry attempts, then return to normal verbosity for routine runs.
Feature-version context
The modern loop keyword was added in Ansible 2.5, and loop_control was added in 2.1. Playbooks targeting older controller versions should verify feature availability before adopting these forms. On supported current Ansible releases, loop is the recommended syntax for ordinary list iteration, while lookup-specific with_* forms remain valid when they communicate intent more clearly.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.

