Skip to content

10 Home Assistant Automation Failures: From Flickering Lights to Trigger Loops

Automations look obvious when you write them and then fall over in the strangest places once they run. I collected the ten failures I see most often. None of them is a "wrong logic" mistake; they are all the trigger / condition / context trio done wrong. Each one comes with the root cause and YAML you can copy.

For the basics (trigger / condition / action, modes) start with Automation basics. The template-breaks-everything case has its own write-up in Jinja2 templating troubleshooting.

1. PIR chatter makes the light flicker

Symptom: the light blinks while you sit still, or it stays on after you leave and turns off when you return.

Root cause: a motion or contact sensor edge bounces. One walk-through fires several times, and the automation re-runs on every bounce.

Fix: require the trigger to hold, or make one event run only once:

trigger:
  - platform: state
    entity_id: binary_sensor.hall_motion
    to: "on"
    for: "00:00:05"   # must hold 5s to count; a single bounce does not

Or set the automation mode so repeats do not stack:

mode: single   # ignore new triggers while running; restart also works

Rule: sensor chatter is the #1 trap. for: plus mode: single kills nine out of ten flicker loops.

2. Two automations fighting over one light

Symptom: one automation says "on when someone is here", another says "off when nobody is here", and the light oscillates between them.

Root cause: you split "on" and "off" into two independent automations. They each evaluate and act, neither knows the other exists, so they race.

Fix: collapse every rule for one device into a single automation and branch with choose:

trigger:
  - platform: state
    entity_id: binary_sensor.hall_motion
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: binary_sensor.hall_motion
            state: "on"
        sequence:
          - service: light.turn_on
            target: { entity_id: light.hall }
      - conditions:
          - condition: state
            entity_id: binary_sensor.hall_motion
            state: "off"
        sequence:
          - service: light.turn_off
            target: { entity_id: light.hall }

Rule: one control surface per device. Branch with choose, never let two automations own the same light.

3. A correct-looking condition never fires

Symptom: add a condition and the automation stops running entirely; remove it and it misbehaves again.

Root cause: you wrote a "state equals X" check inside the trigger context. Trigger-context values only exist at the moment of the trigger. To test the current live state you need a state condition with the entity spelled out.

Fix: know the two kinds of check:

# testing the NOW state: use a state condition with the entity
condition:
  - condition: state
    entity_id: light.hall
    state: "on"

The exact difference between trigger context variables and live state checks is in Trigger vs condition.

Rule: trigger context lives only at trigger time. For the current state, write the entity id in a state condition.

4. "After sunset" runs in the afternoon

Symptom: a sunset automation fires mid-afternoon, or every scheduled time is eight hours off.

Root cause: timezone unset. Time and sun triggers use the system timezone; without it the container runs on UTC.

Fix: confirm the timezone, then make sure the container gets it:

docker run -d --name ha \
  -e TZ=Asia/Shanghai \
  -p 8123:8123 \
  ghcr.io/home-assistant/home-assistant:stable

In the UI, set it under Settings → System → General.

Rule: every "wrong time" mystery starts with the timezone, then the automation's time window.

5. A broken template kills the whole automation

Symptom: you edited a template and the automation simply does not execute; the log is full of Jinja errors.

Root cause: a syntax error (missing bracket, undefined variable, list used as string) makes HA fail to parse the YAML.

Fix: render the template in Developer Tools → Template before pasting it into the automation:

action:
  - service: notify.mobile_app
    data:
      message: "Temp {{ states('sensor.living_temp') }}"

The full debugging path is in Jinja2 templating troubleshooting.

Rule: test the template in Dev Tools, then paste it in. That halves the edit-breaks-everything loop.

6. A dead device makes a condition never pass

Symptom: after one device goes offline, any automation depending on it either hangs or never runs.

Root cause: the condition tests an entity state, but an offline device reports unavailable, which is neither the on nor the off you checked for, so the condition can never be true.

Fix: handle the unavailable state explicitly:

condition:
  - condition: state
    entity_id: binary_sensor.door
    state: "on"
  - condition: template
    value_template: "{{ states('binary_sensor.door') not in ['unavailable','unknown'] }}"

Or guard the action so you never send a command to a dead device.

Rule: any automation that trusts an external device must handle unavailable, or it goes deaf the moment that device drops.

7. Breakage after an upgrade

Symptom: after an upgrade, a previously working automation does nothing, with no error.

Root cause: device triggers/conditions. When a device is re-adopted its device id changes and everything bound to it breaks, while entity ids stay stable.

Fix: always write triggers and conditions against entities, never devices:

trigger:
  - platform: state
    entity_id: light.hall   # stable; a rename touches only this one place

Rule: devices are convenient but fragile; entities are the long-term safe choice. If something broke after upgrade, check for device bindings first.

8. The light re-triggers its own automation (loop)

Symptom: the automation turns the light on, the state flips to on, which triggers "light turned on → turn on" again, and it loops or hangs.

Root cause: the trigger listened to the light's own state change, and the action changed that same state, feeding the event back into itself.

Fix: trigger only on the sensor, never on the controlled device:

trigger:
  - platform: state
    entity_id: binary_sensor.hall_motion
    to: "on"
# do NOT put light.hall in the trigger, or on/off will eat itself

Rule: isolate trigger source from action target. Listen to the sensor, never to the device you are controlling.

9. A weekday-only automation also runs on weekends

Symptom: "turn off lights when leaving for work" fires on Saturday while you are still home.

Root cause: only a time window was used; nothing distinguishes a workday from a weekend.

Fix: add the workday integration (or binary_sensor.workday) as a condition:

condition:
  - condition: state
    entity_id: binary_sensor.workday
    state: "on"

Rule: anything about weekdays/holidays should lean on the workday integration, not hand-written times.

10. 2FA blocks a service call

Symptom: an automation calling a service reports a permission error, but clicking it manually works.

Root cause: that service needs an admin context, and the automation's default context is blocked by 2FA / admin protection.

Fix: confirm whether the service truly needs elevation. Use the automation context described in Automation basics, or declare the required permission explicitly. Safer still: split sensitive operations into steps that need human confirmation rather than letting an automation quietly elevate.

Rule: an automation is not a master key. Services behind admin permission must be granted explicitly; never let an automation bypass 2FA.

Reading the Trace: a debugging order of operations

When an automation misbehaves, do not edit blindly. Open it and click the Trace (the flow icon) on the automation's detail page. The Trace shows every run, which trigger fired, and exactly which step passed or failed. Read it top to bottom before touching a single line.

A useful order of operations:

  1. Confirm the trigger actually fired. If the Trace has no recent runs, the trigger condition was never met — the problem is upstream, in the sensor or the event, not in your automation.
  2. Check the context variable. If a step used a trigger-context value such as trigger.to_state and the data looks empty, the step ran outside trigger time. Switch to a state condition with the entity spelled out.
  3. Look for an exception. A red step means a template or service call threw an error, and the message usually names the exact line.
  4. Test the template alone. Paste it into Developer Tools → Template and watch it render instead of guessing.

Rule: the Trace turns "it is broken" into "step 3 failed because the template referenced an undefined variable". Debug with evidence, not by rewriting in the dark.

The 10-point pre-flight checklist

  1. Sensor chatter → for: on the trigger or mode: single (case 1).
  2. Automations racing → merge into one with choose (case 2).
  3. Condition never fires → use a state condition with the entity for live state (case 3).
  4. All times wrong → check timezone / TZ (case 4).
  5. Template error → test in Dev Tools first (case 5).
  6. Device offline → handle unavailable explicitly (case 6).
  7. Post-upgrade break → use entities, not devices (case 7).
  8. Loop → isolate the trigger source (case 8).
  9. Weekend leak → add the workday integration (case 9).
  10. Permission blocked → grant automation context explicitly (case 10).

Bottom line: automation failures almost always land on three questions: what triggers, what the condition checks, and whose context runs the action. Get those right and even complex logic stays stable. For a node-based alternative to YAML nesting, see Node-RED automations.