What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Ansible conditionals let a playbook decide, for each host and each loop item, whether a task should run. The main keyword is when: give it a raw Jinja expression, and Ansible executes the task only where that expression is true. Facts, ordinary variables, and results registered by earlier tasks are the usual inputs.
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
This guide shows the syntax that works reliably, how conditions interact with loops, imports, failure and change reporting, and check mode, plus a methodical way to diagnose skipped or unexpectedly executed tasks.
As an Amazon Associate I earn from qualifying purchases.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesWhat an Ansible conditional does
A task without a condition is eligible to run on every host targeted by the play. A task with when is evaluated separately for each host after Ansible has the variables and facts needed by the expression. A false expression produces a skipped task on that host; it does not make the play fail.
Conditions are decisions, not text substitutions. The value of when, failed_when, and changed_when is already passed through Jinja2, so do not wrap the expression in {{ }}. The following is valid:
#1 Best Overall
- [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
- [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
- [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
- [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
- [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.
- name: Install a Debian-family package
ansible.builtin.package:
name: nginx
state: present
when: ansible_facts['os_family'] == 'Debian'
Adding {{ }} inside the condition can produce warnings or incorrect evaluation because those delimiters are for templating a value into a string, not for an expression field.
Writing when expressions
One condition
Use a Boolean comparison directly. Facts are commonly addressed through the ansible_facts mapping:
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →- name: Run only on Red Hat family systems
ansible.builtin.debug:
msg: Running the Red Hat family branch
when: ansible_facts['os_family'] == 'RedHat'
You can test a variable, a fact, a registered result, or the result of a filter. If the value might not exist, make that possibility explicit rather than allowing an undefined-variable error.
Several conditions with implicit and
A YAML list under when means every entry must be true. This is usually easier to read than a long line:
- name: Enable a feature on supported production hosts
ansible.builtin.service:
name: myapp
state: started
when:
- app_enabled | bool
- environment == 'production'
- ansible_facts['os_family'] in ['Debian', 'RedHat']
List entries are combined with implicit and. Do not add the word and between list items.
Using and, or, and parentheses
For alternative branches or custom grouping, use a single expression. Parentheses make the intended precedence clear:
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →- name: Apply the compatibility setting
ansible.builtin.template:
src: compatibility.conf.j2
dest: /etc/myapp/compatibility.conf
when: (ansible_facts['distribution'] == 'Ubuntu' and ansible_facts['distribution_major_version'] | int >= 22) or legacy_mode | bool
Without parentheses, a reader has to remember operator precedence and may misunderstand the branch. Keep complicated logic in an intermediate variable when it can be named meaningfully.
Comparing numbers safely
Facts can arrive as strings. Cast a release or threshold before comparing it numerically:
- name: Use the modern repository on supported releases
ansible.builtin.apt_repository:
repo: deb http://example.invalid/myapp stable main
state: present
when: ansible_facts['lsb']['major_release'] | int >= 6
Use | int for whole numbers and | float for decimal measurements. A lexical comparison can otherwise treat values such as 10 and 9 in the wrong order.
Facts and variables as condition inputs
Operating-system facts
The most useful platform facts include ansible_facts['distribution'], ansible_facts['distribution_major_version'], and ansible_facts['os_family']. Choose the fact that matches the decision: an OS family is appropriate for package-manager differences, while an exact distribution or major version is appropriate for a distribution-specific behavior.
Rank #2
- 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
- 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
- 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
- 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
- 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.
Facts are host attributes collected by Ansible, but no fact is universal across every target, connection type, or fact-gathering configuration. Verify that a key exists on the systems you manage before making it a hard prerequisite for a task. If fact gathering is disabled, these values will not be available unless you gather them explicitly.
Fact freshness
ansible_date_time represents the time at which facts were gathered and cached for that host. In a long-running playbook it can become stale. For a time value that must reflect the current moment, obtain it at the point of use rather than treating ansible_date_time as a live clock.
Normalize a decision with set_fact
When the same test appears in several tasks, calculate a clearly named intermediate value once:
- name: Determine whether this host needs the high-temperature profile
ansible.builtin.set_fact:
needs_high_temperature_profile: >-
{{ (temperature | default(0) | float) > 90 }}
- name: Deploy the high-temperature profile
ansible.builtin.template:
src: high-temperature.conf.j2
dest: /etc/myapp/profile.conf
when: needs_high_temperature_profile
The expression in the set_fact value is a normal templated value, so delimiters are appropriate there. They are not appropriate in the later when expression.
Recommended Free Tools
Separate platform data from branching logic
If a playbook accumulates many distribution-specific conditions, separate variable files, templates, or task files can be clearer than deeply nested expressions. A small, well-named platform variable can leave the task itself with one simple condition and make unsupported platforms obvious.
Conditionals based on registered results
Register a task result
register stores the result of a task in a host-level variable for the current playbook run. Common fields include stdout, stdout_lines, rc, failed, changed, and skipped. A later task can branch on those fields:
- name: Check whether the marker exists
ansible.builtin.command: test -f /etc/myapp/marker
register: marker_check
failed_when: false
- name: Rebuild only when the marker is absent
ansible.builtin.command: /usr/local/bin/rebuild-myapp
when: marker_check.rc != 0
The first command normally returns a nonzero code when the file is absent. failed_when: false keeps that expected probe from stopping the play, while the registered return code remains available for the next condition.
Use result tests
Ansible supplies tests that make status checks readable: is failed, is succeeded, is skipped, and is changed. For example:
- name: Report a successful probe
ansible.builtin.debug:
msg: The probe completed
when: probe_result is succeeded
- name: Handle a failed probe
ansible.builtin.debug:
msg: The probe needs attention
when: probe_result is failed
Ansible registers a result for each host even when the task failed or was skipped. That lets later tasks inspect status, but it does not make a missing field safe: check the shape of the result before reading a field that a particular module or execution path may not provide.
Registered variables are not persistent facts
A registered variable lives in memory for the current playbook run and is scoped as host-level data. It is not a cache that will be available on a later run. Persist information deliberately if a future run must make a decision from it.
Rank #3
- [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
- [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
- [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
- [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
- [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by
Inspect command output
Use stdout for the complete text or stdout_lines for a line list. When matching text, make the test explicit and account for the command’s return code as a separate concern:
- name: Check the configured mode
ansible.builtin.command: /usr/local/bin/myapp --show-mode
register: mode_check
changed_when: false
- name: Deploy the fallback configuration
ansible.builtin.template:
src: fallback.conf.j2
dest: /etc/myapp/config.conf
when: mode_check.stdout | trim != 'managed'
Using when with loops
When a task has both a loop and a condition, Ansible evaluates the condition separately for each item. Some items can run while others are skipped:
Free tools Windows power users keep installed
One-click scans. No signup required.
- name: Print only non-privileged ports
ansible.builtin.debug:
msg: '{{ item }}'
loop: [80, 8080, 8443]
when: item > 1024
The item value is available to the expression as item. This per-item behavior is different from a single condition around the whole task: the task can produce a mixture of executed and skipped iterations.
Protect optional loop sources
If a list is optional, default it to an empty list so the task has no iterations instead of failing while resolving an undefined variable:
- name: Configure optional listeners
ansible.builtin.template:
src: listener.conf.j2
dest: '/etc/myapp/listeners/{{ item }}.conf'
loop: '{{ mylist | default([]) }}'
For dictionary data, use an empty mapping and test the value you need:
- name: Enable declared features
ansible.builtin.command: '/usr/local/bin/myapp enable {{ item.key }}'
loop: '{{ feature_map | default({}) | dict2items }}'
when: item.value | bool
Read loop results correctly
When a registered task runs in a loop, the registered variable contains a results list with one response per item. Inspect item.results in a later task, or loop over that list with a different loop variable to avoid ambiguity.
For per-iteration logic that refers to a result from a previous iteration, provide a default for the first iteration. There is no previous result on that first pass, so an unguarded lookup can fail before the condition has a chance to evaluate.
Defining failure with failed_when
failed_when overrides a module’s normal failure decision. This is useful when a command has several meaningful exit codes, or when a nonzero code is expected and should be handled by a later task.
- name: Query application status without stopping on an expected state
ansible.builtin.command: /usr/local/bin/app status
register: app_status
changed_when: false
failed_when: app_status.rc not in [0, 3]
Here, return codes 0 and 3 are accepted; any other code fails the task. The explicit rule documents the contract better than allowing a generic command failure to decide.
Multiple entries in a YAML list under failed_when use implicit and semantics, just like a list under when:
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows 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 #4
- Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
- Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
- All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
- Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
- Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.
failed_when:
- app_status.rc not in [0, 3]
- 'fatal' in app_status.stdout
Use a single expression with or when either condition should fail the task. Pair register with ignore_errors: true when a failure must be recorded and then evaluated by later conditional handling. ignore_errors is different from redefining failure: it allows the play to continue after Ansible marks the task failed.
Defining change with changed_when
changed_when overrides the module’s normal change report. Command and shell tasks often need this because a successful command does not necessarily mean that system state changed.
- name: Query application status without reporting a change
ansible.builtin.command: /usr/local/bin/app status
register: app_status
changed_when: false
failed_when: app_status.rc not in [0, 3]
You can report a change only when output indicates that work occurred:
- name: Refresh the application index
ansible.builtin.command: /usr/local/bin/app refresh
register: refresh_result
changed_when: refresh_result.rc == 0 and 'updated' in refresh_result.stdout
As with failed_when, list entries are joined with implicit and. Correct change reporting matters to handlers, summaries, audits, and any automation that uses the changed status as a signal.
Conditionals on imports, includes, and roles
Static imports
A condition on a static import is applied to all tasks in the imported file. The imported tasks are expanded predictably as part of playbook parsing, so the same condition can affect every task in that file:
- name: Load Debian tasks
ansible.builtin.import_tasks: debian.yml
when: ansible_facts['os_family'] == 'Debian'
This is convenient when the entire file belongs to one platform branch. Remember that the condition is inherited by each imported task; a task that changes a variable does not retroactively alter how the already-expanded branch is selected.
Dynamic includes
A dynamic include is evaluated at runtime. Variables can change before the include is reached, and the include decision is made then:
- name: Load platform tasks at runtime
ansible.builtin.include_tasks: platform.yml
when: platform_tasks_enabled | bool
Choose an import for predictable static expansion and an include when the decision must occur dynamically or when the included content depends on state established earlier in the play.
Roles
Conditions can also be attached when reusing a role. Put the platform or environment decision at the reuse boundary when the whole role is optional; keep task-level conditions inside the role for decisions that vary between individual tasks. This keeps the role’s interface understandable and avoids repeating the same branch on every task.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Check mode and conditional branches
Check mode simulates changes. Run it with:
ansible-playbook site.yml --check
Supported modules report what they would change without modifying remote systems. Add diff mode when the module supports it to see proposed file differences.
Best Value
check_mode: true forces an individual task to run in check mode. check_mode: false forces normal execution for that task even when the playbook was launched with --check. Use the latter sparingly, because it intentionally performs a real operation during a simulation.
A check-mode run cannot always provide ordinary registered-result output. If a preceding task is skipped or does not execute its normal operation in simulation, a later condition that depends on its registered fields may have no useful data. Design such branches with an explicit check-mode path, or guard access to optional result data.
- name: Show the planned action when the probe has run
ansible.builtin.debug:
msg: The marker probe returned {{ marker_check.rc }}
when:
- not ansible_check_mode
- marker_check is defined
This example deliberately avoids reading a result that may not exist during a pure simulation. The exact approach depends on whether the command is safe and supported in check mode.
A complete conditional playbook pattern
The following example combines platform facts, a registered probe, per-item filtering, and explicit failure and change semantics:
---
- name: Configure the application
hosts: app
become: true
tasks:
- name: Gather the normal host facts
ansible.builtin.setup:
- name: Install the Debian-family package
ansible.builtin.package:
name: nginx
state: present
when: ansible_facts['os_family'] == 'Debian'
- name: Check whether the application is already initialized
ansible.builtin.command: test -f /etc/myapp/initialized
register: initialization_check
failed_when: false
changed_when: false
- name: Initialize the application
ansible.builtin.command: /usr/local/bin/myapp init
when:
- initialization_check.rc != 0
- not ansible_check_mode
- name: Configure enabled ports
ansible.builtin.template:
src: port.conf.j2
dest: '/etc/myapp/ports/{{ item }}.conf'
loop: '{{ app_ports | default([]) }}'
when:
- item | int > 1024
- app_ports_enabled | default(true) | bool
- name: Query service status
ansible.builtin.command: /usr/local/bin/myapp status
register: service_status
changed_when: false
failed_when: service_status.rc not in [0, 3]
- name: Start the service when it is stopped
ansible.builtin.service:
name: myapp
state: started
when: service_status.rc == 3
The probe tasks are intentionally non-changing, the expected status code is accepted, the loop has a safe default, and initialization is excluded from check mode because it is an operation rather than a simulation.
Why a conditional is skipped or fails
The expression contains {{ }}
Remove the delimiters from when, failed_when, and changed_when. Those fields already evaluate Jinja expressions.
The fact or variable is absent
Inspect the available data and confirm fact gathering. A fact name that exists on one operating system may not exist on another. Use default only when the fallback is semantically safe; a default that silently selects the wrong platform can be more dangerous than a deliberate failure.
A number is being compared as text
Cast release numbers and measurements with | int or | float before comparing them.
A registered result has an unexpected shape
Inspect the complete result, then choose the correct field: stdout, stdout_lines, rc, failed, skipped, or, for loops, results. A task that was skipped may have status metadata but no command output.
An optional loop variable is undefined
Use loop: {{ mylist | default([]) }} for optional lists and default({}) for optional mappings. In actual YAML, the expression is quoted as shown in the examples so the complete templated value is parsed consistently.
Check mode removed the data needed by the branch
Remember that simulation can skip or alter the task that would have populated a registered result. Test the normal run and check-mode run separately, and add an explicit check-mode guard when the operation cannot produce meaningful simulated output.
Quick Recap
A practical debugging checklist
- Display the relevant data with
ansible.builtin.debug: var=ansible_factsor a targeted variable. - Confirm that the condition is a raw expression and contains no
{{ }}. - Verify that strings, integers, and floating-point values are being compared as the intended types.
- For registered results, inspect
stdout,rc,failed,skipped, and loopresults. - Add
default([])ordefault({})to genuinely optional loop inputs. - Run
ansible-playbook site.yml --checkand account for branches that depend on results unavailable during simulation. - Read the skip reason in Ansible’s verbose output; it often identifies the evaluated expression or the missing variable.
Choosing the right conditional pattern
| Decision need | Recommended pattern | Important behavior |
|---|---|---|
| Different operating-system behavior | Fact-based when |
Evaluated independently for every host; verify the fact exists. |
| Several requirements must all hold | YAML list under when |
Entries use implicit and semantics. |
| Alternative branches or custom grouping | One expression with and, or, and parentheses |
Parentheses document precedence and prevent accidental grouping. |
| Decision based on an earlier command | register plus a later condition |
Results are host-level and temporary; skipped or check-mode tasks may not provide normal output. |
| Only some loop items qualify | when alongside loop |
The condition is evaluated separately for each item. |
| One platform file should always share a branch | Conditioned static import | The condition applies to all tasks in the imported file. |
| Branch selection must use runtime state | Conditioned dynamic include | The include is evaluated when execution reaches it. |
| A command’s exit code is not its true failure rule | failed_when |
Define accepted and rejected outcomes explicitly. |
| A successful command should not always report change | changed_when |
Accurate change status improves idempotence reporting and handler behavior. |
| Preview supported changes | --check, optionally with diff mode |
Registered-result-dependent branches may lack data in simulation. |
Key rules to remember
whenis a raw Jinja expression evaluated per host; omit{{ }}.- Facts, ordinary variables, and registered results are the normal sources for decisions.
- Lists of conditions mean implicit
and; use a single expression when you needoror explicit grouping. - Cast strings before numeric comparisons.
- Loop conditions run per item, and optional loop data should have safe defaults.
- Registered variables last only for the current playbook run and contain a
resultslist when the task used a loop. failed_whenandchanged_whenlet you define outcome semantics instead of relying on a command’s default status.- Check mode is a simulation, and it may not populate the registered data that a later conditional expects.
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.




