Automation cannot trigger itself?

Is an automation not allowed to manually trigger itself?

I have an automation with nested loops which due to variable scope is difficult/impossible to break out of. Eventually, I figured an easy solution would be have the automation run in mode: restart and simply trigger itself.

This however does not work. The current execution does stop, but the new execution fails without any explanation. Looking in traces it simply says that:

  • Triggered manually at [date] at [time]
  • Stopped because of unknown reason at [date] at [time] (runtime: 0.01 seconds)

Is this a bug? Some inexplicable limitation? Something I am overlooking?

Automation reduced down to bare minimum test case:

triggers: []
actions:
  - if:
      - condition: template
        value_template: "{{ this.attributes.current > 0 }}"
    then:
      - action: notify.persistent_notification
        data:
          message: Triggered by myself, but fails before this notification?
    else:
      - action: notify.persistent_notification
        data:
          message: Preparing to trigger myself.
      - action: automation.trigger
        target:
          entity_id: "{{ this.entity_id }}"
      - action: notify.persistent_notification
        data:
          message: Automation should stop before this notification.
mode: restart

Generally you shouldn’t trigger automations manually.
What you have done is essentially made the automation a script.
Triggering the same script multiple times should however work fine

Why though? An automation should be able to do anything that can be done manually.

If I add a delay: 10 to the automation and manually run it twice (as in selecting Run actions from the … menu on the Automations page) so that the second run happens during the delay in the first, the first run is stopped and the correct actions are executed in the second run. It only fails when it is the automation that manually triggers itself.

What I posted above is only a simplified test case. My real automation/blueprint is obviously much more complicated and has other triggers. It cannot be run as a script.

An automation that is triggered by something is a script.
There is no reason to trigger an automation, use a script instead and you can send variables with the call

“This is the way”. There is not much documentation (that I can find) on how to pass variables from an automation to a script, but I can quickly show you an example (in mine I actually made some scripts generic by passing entities to the scripts from a variety of different automations - where I needed the same logic used (rather than replacing code all over the place).

Scripts does not have triggers. Why should I make things more complicated and split my code between an automation and a script, when this is clearly a bug that should be fixed?

Who made you the arbiter of how Home Assistant is allowed to be used? I thought the thread about gatekeeping was a tad bit hyperbolic, but here it is plain to see. My way or the highway.

If you come here and ask for help then you will get help.
If you think it’s your way or the highway then you are wrong. Most of the times threads are solved in a way that the thread starter did not think of.
So who is gatekeeping?

It’s less an issue of “allowed” and more an issue of “best practice”.

You’re certainly free to attempt to use automations and scripts in a manner that strays from “best practice”. The results occasionally lead to what you have encountered.
It’s not necessarily due to any bug but just that it wasn’t designed to operate the way you thought it would.

If you strongly believe it is a bug, it’s best to report it in the Core repository. The Core development team will decide if it’s a bug (fails to work as documented) or a feature request (request to have it work differently).

1 Like
  • When an automation is not executing its actions, its current attribute reports 0.

  • If one or more instances of the same automation are busy executing actions, the value of current represents the number of concurrent instances. So it will be 1 if one instance of the automation is busy executing its actions.

Given that information, why does the example you posted use a Template Condition to check if its own current value is greater than zero?

While it’s processing that Template Condition in the if statement, its current value will be minimally 1. Under what circumstances do you foresee it could be zero while it’s processing actions? I don’t see how it could ever reach the else portion.


EDIT

Nope; I was wrong. :man_facepalming:

The this object contains values prior to the execution of the actions, so current will contain the automation’s previous state. So if given concurrent instances of an automation, the first instance’s current value will be 0 (not 1).

Just FYI, according to the docs a defined trigger is required for automations. You can search these forums and find dozens of threads where users tried to create automations without defined triggers, only to find they don’t work as expected.

If you are using a test case or real automation that do not have defined triggers, you are shooting yourself in the foot.

Hi,
Are you able to go into a bit more detail about what you are trying to achieve with your automation. Maybe the community can suggest some other ideas to help you solve this if we know more about what the end result should look like.
Cheers
Nick

I explained that in the second paragraph of my first post:

I have a decently complex automation with parallelized actions and nested loops. The only way I have found for one part of the automation to be able to interrupt what all of the others may or may not be doing is to run the automation in mode: restart and then simply trigger the automation again.

Checking whether this.attributes.current > 0 lets me know if the automation was restarted when already in progress, or if this is its initial run from a previously idle state. If this is not how I am supposed to detect whether a restart has occurred, then how am I supposed to do it?

(I also have some automation triggers which should only be acted upon in a restart scenario.)

Ohh, and by the way:

That is completely wrong. Give it a try and you will see. Here is how the documentation describes this:

The variable this is the state object of the automation at the moment of triggering the actions. State objects also contain context data which can be used to identify the user that caused a script or automation to execute. Note that this will not change while executing the actions.

Don’t know how you would interpret that, but my interpretation is that the values of this are set before actions are executed, and once actions are in progress this never changes. Or at least that is how it works in practice in my experience.

Thus for an automation in mode: single I would expect this.attributes.current to always be 0. For an automation in mode: parallel it would show number of already running threads before the execution of the “current” thread. For an automation in mode: restart it will be 0 if started from idle, or 1 if restart occurred with a thread already in progress. Haven’t looked into how mode: queued is handled.

1 Like

My real automation has several triggers, and inserting a dummy trigger in the test case makes no difference.

You’re absolutely right. I tested and confirmed it behaves the way you described.

For an automation in mode: restart it will be 0 if started from idle, or 1 if restart occurred with a thread already in progress

I have amended my post above to prevent misleading others.

I have now worked around this by instead firing a custom event and adding a corresponding custom event trigger. Initially I was hesitant to do this as triggering the automation directly seemed more efficient and would work even if the automation was manually disabled during its initial run, but I did not take into account that disabling the automation would also stop it.

But either way, I still believe this is a bug, and the right thing to do would be to fix it – regardless of whether it goes against someone’s dogma of how HA “should” be used.