Memory drain with big trace caused by wait for trigger optional timeout issue in visual editor

Hi,

I recently noticed that I had issue with over a 1GB of memory was taken shortly after 10pm and over a couple of days the amount of memory taken by Home assistant went down around another 1GB. Restarting home assistant brought the memory back but after I determined that it was one of my automations which had a repeat script that contained a wait for trigger with “continue on timeout” and timeout of 0:0:0:0 which shows as optional in the visual editor.

The trace repeat itself creating thousands of entries continually filling up the automation trace screen.

In testing I found out that it was more to do with the wait for trigger;

If you don’t touch the timeout (optional) I think you are ok, but if you change it and even change it back to the default value of all 0’s and click on show in Edit in YAML

wait_for_trigger:
  - platform: state
    entity_id:
      - binary_sensor.lg_h850_interactive
    to: "off"
    for:
      hours: 0
      minutes: 0
      seconds: 10
continue_on_timeout: false
timeout:
  hours: 0
  minutes: 0
  seconds: 0
  milliseconds: 0

it shows the timeout section, so this has the effect of not waiting for the trigger. You may as well have a if condition for that.

If I edit out the timeout in the YAML and save the automation it does wait for the trigger as expected.
e.g.

wait_for_trigger:
  - platform: state
    entity_id:
      - binary_sensor.lg_h850_interactive
    to: "off"
    for:
      hours: 0
      minutes: 0
      seconds: 10
continue_on_timeout: false

You can’t revert back the value in the visual editor and it isn’t obvious whether it has a value set other than going into the YAML editor. Shouldn’t it be set so that if the value is 0 (or no value) for all those it should clear out the timeout section?

Thanks!

As you just provided the wait for trigger part, I suppose your repeat action looks something like this?

repeat:
  sequence:
    - wait_for_trigger:
        - platform: state
          entity_id:
            - binary_sensor.lg_h850_interactive
          to: "off"
          for:
            hours: 0
            minutes: 0
            seconds: 10
      continue_on_timeout: false
      timeout:
        hours: 0
        minutes: 0
        seconds: 0
        milliseconds: 0
    - service: something.something
      metadata: {}
      data: {}
      target:
        entity_id: somesthing.something
  until:
    - condition: state
      entity_id: sensor.some_sensor
      state: ON

If you do it this way (inside a repeat action) the actions will get “repeated” as implied, however as you probably don’t have a delay in front of the wait for trigger action it repeats these actions as fast as it can, and thereby generating thousands of iterations a second (increasing memory)

I had this exact issue, and it led to my HA crashing multiple times.

I can’t say under which circumstances this happens with wait for the trigger (but I assume that per default the “0” equates to no timeout (indefinite wait time) and if you change it “also to 0” it literally means 0 seconds “or instant timeout”) If the timeout is literally 0 seconds it will skip the action (as continue on timeout is false) and repeat as fast as the system can get.

So just to be safe, I generally add a small delay at the very front of these repeat actions. Thereby limiting the iterations to X amount per Y timeframe. Then you can fix or improve the action inside the repeat action without it nuking the system every time it gets launched.

repeat:
  sequence:
    - delay:
        hours: 0
        minutes: 0
        seconds: 1
        milliseconds: 0
    - wait_for_trigger:
        - platform: state
          entity_id:
            - binary_sensor.lg_h850_interactive
          to: "off"
          for:
            hours: 0
            minutes: 0
            seconds: 10
      continue_on_timeout: false
      timeout:
        hours: 0
        minutes: 0
        seconds: 0
        milliseconds: 0
    - service: something.something
      metadata: {}
      data: {}
      target:
        entity_id: somesthing.something
  until:
    - condition: state
      entity_id: sensor.some_sensor
      state: ON

Also, may I ask what the use case is for using the wait for trigger action inside a repeat action?

Included is my action:

repeat:
  sequence:
    - if:
        - condition: state
          entity_id: binary_sensor.lg_h850_interactive
          state: "off"
      then:
        - service: light.turn_on
          data:
            brightness_step_pct: -5
            transition: 20
          target:
            entity_id:
              - light.bedroom
        - delay:
            hours: 0
            minutes: 0
            seconds: 20
            milliseconds: 0
      else:
        - wait_for_trigger:
            - platform: state
              entity_id:
                - binary_sensor.lg_h850_interactive
              to: "off"
              for:
                hours: 0
                minutes: 0
                seconds: 10
          continue_on_timeout: true
  until:
    - condition: state
      entity_id: light.bedroom
      state: "off"

Basically it slowly dims the bedroom lights and if the lg is switched on the bedroom lights don’t dim further until it is switched off.

I did switch it to wait for 1 minute, but it was strange outside of the repeat if I put in a wait for trigger it indefinitely waited. Would it be considered an issue that the visual editor isn’t indicating whether it is no longer optional and defined?

Your Delay Action is after the light.turn_on action in the if statement.

If that is false, it won’t add the delay, thereby still looping too fast.
I’m sorry, I should have said at the very beginning of the repeat action, before everything else.

Also, I think the Wait for trigger in this scenario is unnecessary. I would use a condition followed after the intended action. If the condition doesn’t equate to true. The Action does not fire. I see what you are trying to achieve with the wait for trigger, however in this instance it is not required. You could instead do it like this and check every iteration (X seconds):

repeat:
  sequence:
    - delay:
        hours: 0
        minutes: 0
        seconds: 1
        milliseconds: 0
    - condition: state
      entity_id: binary_sensor.lg_h850_interactive
      state: "off"
    - service: light.turn_on
      data:
        brightness_step_pct: -5
        transition: 20
      target:
        entity_id:
          - light.bedroom
  until:
    - condition: state
      entity_id: light.bedroom
      state: "off"

Or just with the Wait for Trigger, but with a timeout (that replaces the delay at the beginning) You can even increase the Delay as it is actively listening for State changes and not just waiting.

repeat:
  sequence:
    - wait_for_trigger:
        - platform: state
          entity_id:
            - binary_sensor.lg_h850_interactive
          to: "off"
      timeout:
        hours: 0
        minutes: 0
        seconds: 20
        milliseconds: 0
      continue_on_timeout: false
    - service: light.turn_on
      data:
        brightness_step_pct: -5
        transition: 20
      target:
        entity_id:
          - light.bedroom
  until:
    - condition: state
      entity_id: light.bedroom
      state: "off"

Note that in that case the light.turn_on action would fire repeatedly, as you have a transition time you probably don’t want multiple events in that timeframe. In that case, you could still add the Delay in front of everything and adjust the Delay accordingly.

Yeah the delay action is in the correct place, it’s to allow the set light brightness to transition by the same amount as the set light call doesn’t wait for it to complete otherwise,

I’ve previously gone between removing the timeout value in YAML and a delay of a minute - Both results with a smaller trace log - so no longer drains the which results in a smaller trace log. So it works now the way I want to thanks :slight_smile:

My only question now is that is it worthwhile logging it as an issue about the visual editor doesn’t show that the value is not the default or not if all values are 0 and have a way of removing that value if hours minutes and seconds to 0 is a valid value to cause it to immediately timeout if there is no trigger.

You should report it as a bug.
It is definitely not intended this way.
As said earlier the initial value probably means wait indefinitely and when change, then it is interpreted as a value of 0.
It is a missing value check in the code.

Ah, okay, then your delay action makes sense with the 20 seconds and the transition time. As stated, the wait for trigger will only fire on state changes. And as you said, the delay of a minute reduces iterations.

I think you could report this as a bug, like already said before.
I just tested this (removing zeros from UI etc.) and you’re right, once a timeout is entered it remains in YAML. The same is presumably true for all “optional” UI Fields. It’s confusing that in this case it literally means 0 seconds instant timeout (so basically useless for this action)

This probably tripped more people up already, so it’s definitely a good idea to report this.

I’ve logged it under wait for trigger optional timeout issue · Issue #19360 · home-assistant/frontend (github.com)

Hopefully I explained it ok :smiley: