The short answer
One Choose block works like an if / else-if / else chain. Home Assistant checks its options in order and runs only the first option whose conditions all pass; later options are skipped even when their conditions also pass. If no option matches, the default action sequence runs. Whatever you place after the Choose block still runs (Choose building block).
A single If-then-else picks one side: the then sequence when the conditions pass, otherwise the else sequence, never both. Two separate If-then blocks are different. Each one is evaluated when the script reaches it, so both can run in the same script run if both conditions pass at that moment (If-then building block). Two independent Choose blocks placed one after the other behave the same way.
Where to paste the complete examples
Both blocks below are complete script objects. In Home Assistant, open Settings > Automations & scenes > Scripts, create a new script, then choose Edit in YAML and replace the editor content with the whole block, from alias: through the last step of sequence:. Menu labels vary by version, so look for the YAML editor rather than an exact button name.
Paste the script object itself. These blocks are for one script's UI YAML editor, not the automation editor or a complete scripts.yaml file; file-based definitions require their own script-identifier mapping. These are expected logical examples built from the documentation, not recordings from a live Home Assistant instance; they use only the built-in persistent notification integration, with no devices or added integrations.
One Choose with two true conditions
Example 1 sets a and b to true, so both options match. Only option A runs, because it comes first, and B is skipped. The notification after the Choose block still runs.
alias: "Choose vs If - one Choose, both conditions true"
variables:
a: true
b: true
mode: single
sequence:
- choose:
- conditions:
- condition: template
value_template: '{{ a }}'
sequence:
- action: persistent_notification.create
data:
title: "Choose: option A"
message: "a is true, and A is the first matching option."
notification_id: choose_a
- conditions:
- condition: template
value_template: '{{ b }}'
sequence:
- action: persistent_notification.create
data:
title: "Choose: option B"
message: "b is true and no earlier option matched."
notification_id: choose_b
default:
- action: persistent_notification.create
data:
title: "Choose: default"
message: "Neither option matched."
notification_id: choose_default
- action: persistent_notification.create
data:
title: "End marker"
message: "The sequence continued after the Choose block."
notification_id: choose_endTwo If actions with the same two conditions
Example 2 uses the same variables and the same notification-only setup, but two standalone If-then blocks. Both blocks are reached in order and both conditions pass, so both notifications appear.
The examples omit else only to keep them short. Two consecutive If blocks can each have their own else and stay independent; what changes the logic is nesting the second If inside the first If's else.
alias: "Choose vs If - two standalone If actions"
variables:
a: true
b: true
mode: single
sequence:
- if:
- condition: template
value_template: '{{ a }}'
then:
- action: persistent_notification.create
data:
title: "If: A"
message: "The first If ran."
notification_id: if_a
- if:
- condition: template
value_template: '{{ b }}'
then:
- action: persistent_notification.create
data:
title: "If: B"
message: "The second If ran."
notification_id: if_b
- action: persistent_notification.create
data:
title: "End marker"
message: "The sequence continued after both If blocks."
notification_id: if_endExpected output for all four cases
a | b | One Choose | Two If actions |
|---|---|---|---|
true | true | A | A then B |
true | false | A | A |
false | true | B | B |
false | false | default | neither |
The end marker runs in every row, but only on normal completion: a stop action or an error before that step ends the run, and no later notification appears. The Choose column never lists two branches, and the If column lists two only when both conditions pass.
Run mode is not a branch switch
mode: single means a new run of the script is not started while the previous run is still going. The other modes are restart, queued and parallel, and each one decides what happens when the whole script is started again, not which option inside one Choose may run (Scripts integration). Setting mode: parallel does not make two options inside one Choose both run; that behavior comes only from using independent blocks.
What can change the result
Conditions are evaluated when the script reaches them, so a condition that passed earlier can fail by the time its step runs. A delay, a stop, an error, or an earlier action that changes the state being tested can all change which branches run later. The fixed boolean variables remove those moving parts so the branch logic is visible in isolation.
Avoid nesting the second If inside the first If's else when you want both conditions checked. Inside an else, the second block is evaluated only when the first condition fails, which is different logic. When branches are mutually exclusive, one Choose is the clearer tool; when you need independent checks, use one block per check.
How to check which branch ran
- Start the script, then open its trace.
- In Example 1, the trace should show only one option sequence executing, with no B or default notification.
- In Example 2, both If sequences should appear in order, each with its own notification.
- Compare the notifications. Each
notification_idhere is stable and distinct (choose_a, choose_b, choose_default, choose_end, if_a, if_b, if_end), so a rerun overwrites only the notifications whose branch actually ran. A branch skipped this run keeps its notification from an earlier run. Before testing a different combination ofaandb, dismiss only the notifications from these two examples, named above, or compare traces run by run; do not clear every notification on your system.
The title, message and notification_id fields are defined in the persistent notification action and the Persistent Notification integration.
If you route several triggers into one automation instead of choosing between conditions inside one script run, that is a different task: see Home Assistant trigger IDs: one automation, multiple branches.



