`for` in `template` trigger does not have access to variables defined in the automation

As mentioned in the title, the for attribute on the template does not have access to variables defined in the script/automation. This was specially confusing for me since the documentation does not mention this being a special case, nor any errors or warnings are raised if for: renders to some invalid data. Is this expected behaviour?

Here’s a minimal test to validate what I’m experiencing. The following code will get a for: { seconds: 2 } meaning that test_sensor is accessible in that scope.

alias: "Test: wait template for"
description: ""
trigger: []
condition: []
action:
  - variables:
      # change this to any sensor you can use to test
      test_sensor: binary_sensor.macroled_mini_relay_3_switch_2
  - wait_for_trigger:
      - platform: template
        value_template: "{{ is_state(test_sensor, \"on\") }}"
        for:
          seconds: "{{ 1 if test_sensor is defined else 2 }}"
mode: single

Try it like this:

alias: "Test: wait template for"
description: ""
variables:
  # change this to any sensor you can use to test
  test_sensor: binary_sensor.macroled_mini_relay_3_switch_2
trigger: []
condition: []
action:
  - wait_for_trigger:
      - platform: template
        value_template: "{{ is_state(test_sensor, \"on\") }}"
        for:
          seconds: "{{ 1 if test_sensor is defined else 2 }}"
mode: single

Does this also work if I modify the variable within the automation? I’m doing this inside a while loop and the timer varies each iteration (exponential backoff).

Yeah if you define the variable at the top level of the automation it should be available everywhere inside the automation.

Didn’t work, the variable is not defined. Tried it with this:

alias: "Test: wait template for"
description: ""
trigger: []
condition: []
action:
  - variables:
      test_sensor: binary_sensor.macroled_mini_relay_3_switch_2
      must_be_true: true
  - wait_for_trigger:
      - platform: template
        value_template: "{{ is_state(test_sensor, \"on\") }}"
        for:
          # 1: defined correctly
          # 2: defined but previous block didn't change the value
          # 3: not defined at all
          seconds: "{{ (1 if must_be_true else 2) if must_be_true is defined else 3 }}"
variables:
  must_be_true: false
mode: single

got seconds: 3

Even if the variable is available everywhere, I don’t think that guaratees that it’ll have the an up to date value, it could just hold the value defined in the variables: section outside the action list.

I have no idea what you are taliking about.

Here’s an example

must_be_true = False
print(must_be_true)

def test():
  must_be_true = True
  print(must_be_true)
test()

print(must_be_true)

Prints false true false

All pieces of code reference the same identifier but not the same value. The for template might be able to reference the variable at the variables section but not the updated value set in the actions section.

Either way using the variables section didn’t work so this distinction is kinda pointless.

Nope. By defining the varable at the top level the variable is global to the automation and actions are executed in sequence. So after the test action the variable has been updated and it would actually print:

false true true.

EDIT: I was completely wrong. See below.

@TheFes over on discord was able to reproduce this, so yes this seems to be a bug. In typical Home Assistant fashion this took about two days to debug. I’ve opened this issue to report the bug: `for` in `template` trigger does not have access to variables defined in the automation · Issue #105979 · home-assistant/core · GitHub

In the meantime it would be cool to have a workaround to have this automation finally work :stuck_out_tongue:

1 Like

Also this is completely wrong, apologies:

See: https://www.home-assistant.io/docs/scripts/#scope-of-variables