Loop until executes even after condition evaluates true

I have an automation that turns on the lights when frigate detects a person. I am trying to loop until the frigate event that triggered the automation sends an ‘end’ event or the loop times out. I tried many different ways, but the loop keeps executing even after the event end message is received. current code:


event_ended variable is set to false before loop starts
id is captured from original frigate event that triggered the automation



alias: Loop until end event is received or timeout happens.
repeat:
  sequence:
    - alias: Wait for an MQTT message or loop timeout
      wait_for_trigger:
        - alias: MQTT message with matching event ID
          topic: frigate/events
          value_template: >-
            {{ wait.trigger.payload_json['after']['id']|string() == id|string()
            and wait.trigger.payload_json['type']|string() == 'end' }}
          trigger: mqtt
      continue_on_timeout: true
      timeout:
        hours: 0
        minutes: 1
        seconds: 0
        milliseconds: 0
    - variables:
        event_ended: >-
          {% if event_ended != true %}
            {% if wait.trigger is defined and wait.trigger.payload_json is defined %}
              {{ wait.trigger.payload_json['after']['id']|string() == id|string() and wait.trigger.payload_json['type']|string() == 'end' }}
            {% else %}
              false
            {% endif %}
          {% endif %}
  until:
    - alias: Event end is received for triggering event that started automation
      condition: template
      value_template: "{{ event_ended != false }}"

I had logging in the loop and event_ended is correctly set to true when id matches and event type = ‘end’ however loop is not exited.

Another issue is that MQTT triggers on any event id and message type. this should not matter since values are checked when event_ended is set, but ideally this loop would only fire once then exit.

Here’s an example log where iteration 7 evaluated as true, but it kept running iteration 8 & 9

Iteration 7
Executed: March 20, 2025 at 3:19:56 AM
Result:

params:
  domain: logbook
  service: log
  service_data:
    name: Front Lights
    domain: automation
    entity_id: automation.frigate_notification_mqtt_front_door_lights
    message: >-
      person was detected on Front Door camera - repeat loop iteration=7  

      Event ID from automation trigger= 1742455179.136992-xmkwvn  New event ID
      is defined= 
        original event id= 1742455179.136992-xmkwvn
        after event id=>>>1742455179.136992-xmkwvn<<<
        original variable type= update
        payload_json type= ------>end<------ 
        before time=--->1742455180.045057<---
        after  time=--->1742455191.272018<---
        
       event_ended=True
  target: {}
running_script: false

Iteration 8
Executed: March 20, 2025 at 3:19:57 AM
Result:

params:
  domain: logbook
  service: log
  service_data:
    name: Front Lights
    domain: automation
    entity_id: automation.frigate_notification_mqtt_front_door_lights
    message: >-
      person was detected on Front Door camera - repeat loop iteration=8  

      Event ID from automation trigger= 1742455179.136992-xmkwvn  New event ID
      is defined= 
        original event id= 1742455179.136992-xmkwvn
        after event id=>>>1742455180.368356-ty48sp<<<
        original variable type= update
        payload_json type= ------>end<------ 
        before time=--->1742455190.962753<---
        after  time=--->1742455191.965489<---
        
       event_ended=False
  target: {}
running_script: false

Solution is to use namespace:

Jinja2’s scoping rules prevent variables assigned within loops or conditional blocks from being directly returned or used outside of those blocks. To circumvent this limitation and maintain variable values across different parts of a Jinja2 template, you must employ the namespace object, which provides a mutable scope for storing and accessing variables throughout the template’s execution.

or you can store values in helper variables as well.