Z2M restart republish indistinguishable from physical user action — context filtering false positives

If you use trigger.to_state.context to detect physical switch presses in your HA automations, a common and recommended pattern for occupancy logic, manual override detection, or presence sensing, you are probably getting false positives when Zigbee2MQTT restarts.

The problem

When Z2M restarts, paired devices republish their current state to Home Assistant. The context on these republished state changes is identical to a genuine physical user action:

Action parent_id user_id id
Physical toggle null null not null
Automation triggered not null null not null
Dashboard/UI tap null not null not null
Z2M restart republish null null not null

There is no way to distinguish a restart republish from a real physical toggle at the HA context level. This means any automation using the standard three-condition physical switch filter:

yaml

  • condition: template value_template: >- {{ trigger.to_state.context.parent_id is none and trigger.to_state.context.user_id is none and trigger.to_state.context.id is not none }}

…will fire on a Z2M restart as if someone physically touched every switch in the house.

Who is affected

Anyone using context filtering to detect physical user actions: occupancy automations, wasp-in-a-box logic, presence/proof-of-life detection, manual override detection. Z2M restarts happen after power failures, coordinator disconnects, and scheduled HA reboots. This is silent noise that is hard to diagnose because the false triggers look exactly like real events in the trace.

Workaround

Add a time-based suppression condition to your physical switch detection automations. Gate the context filter on how long Z2M has been connected:

yaml

  • alias: Z2M has been connected long enough — not a restart republish condition: template value_template: >- {{ (now() - states.binary_sensor.zigbee2mqtt_bridge_connection_state .last_changed).total_seconds() > 60 }}

binary_sensor.zigbee2mqtt_bridge_connection_state transitions to on when Z2M reconnects. Any switch state changes within 60 seconds of that transition are likely restart republishes and will be suppressed. Adjust the threshold to match your environment. 60 seconds should cover most setups but larger meshes may need more time.

For advanced users running AppDaemon, a more robust approach is to fire custom zigbee_restart_started and zigbee_restart_complete events from your Z2M recovery automation and use a suppression window in your AppDaemon scripts to ignore all Zigbee signals during reconnect.

The fix

I’ve opened a feature request with the Z2M team asking them to add a z2m_source field to restart republish payloads:

json

{“state”: “ON”, “z2m_source”: “restart_republish”}

Normal device-triggered state changes would omit this field. HA automations could then filter on trigger.to_state.attributes.z2m_source != 'restart_republish' — no changes to HA core required, purely a Z2M payload addition.

GitHub issue: [Feature request]: State republish on restart should set context to distinguish from physical user action · Issue #31766 · Koenkk/zigbee2mqtt · GitHub

1 Like

With all no due respect to whichever AI led you down this rabbit hole, there’s a much simpler way to overcome this which everyone’s been using for ages.

For entities which use state (but not numeric_state), you can use this in the trigger:

trigger: state
entity_id:
  - sensor.your_sensor
not_from:
  - unavailable
  - unknown

For all entities, including ones which have a numeric state, you can use this condition.

condition: template
value_template: "{{ trigger.from_state.state not in ['unknown', 'unavailable'] }}"

The advantage to using the above condition is that it doesn’t depend on the last Z2M message being less than 60s ago. It will also cover the edge case you’re missing, when there’s a hiccup in starting Z2M and the (default) watchdog timer kicks in after 1 minute.

Ref docs for the trigger are here. Can’t remember where I saw the reference for the condition - I probably stole it from someone who posted it on the forums, but I can guarantee it’s bulletproof.

2 Likes

The community guide use that solution too. How to use context

I am sorry, but your solution will show any switch toggle from on to off or off to on, from wherever it is caused, whether it be a human toggling the switch, or an automation or script. With “all no due respect”, maybe you should read before you comment.

I’ve written up the full solution including the three-condition filter, the event pattern architecture, and the Z2M suppression workaround in a detailed article here:

I hope it helps anyone else hitting this problem.

Restarting Z2M will put the switch in an unknown/unavailable state in HA until that “restart republish” message is fired.

Setting the automation to ignore changes from unknown/unavailable states ensures this doesn’t create false triggers, irrespective of the integration being used.

Feel free to try it out for yourself, because it literally guards against

1 Like