Introduction
I walked into the kitchen, ready to start the dishwasher. Pressed the button. Nothing. The smart plug was off.
Weird. I turned it back on via Home Assistant. A few hours later, same thing - the plug was off again. No automation should be touching it. What was going on?
What followed was a debugging journey through MQTT logs, Zigbee protocol quirks, and a fundamental misunderstanding of how Zigbee groups actually work. If you’re using zigbee2mqtt and have ever removed a device from a group only to find it still responding to group commands, this post is for you.
The Mystery: A Smart Plug with a Mind of Its Own
The setup was simple:
- A smart plug (
dishwasher_plug) powering the dishwasher - A Zigbee group (
ZG_Bedroom_Lights) controlling the bedroom lights - No automation linking the two
Here’s the twist: the smart plug used to live in the bedroom. Months ago, I had it controlling a lamp and it was part of the ZG_Bedroom_Lights group. When I repurposed it for the dishwasher, I did everything “by the book”:
- Deleted the device from zigbee2mqtt
- Re-added it (full interview process)
- Renamed it to
dishwasher_plugand regenerated entity IDs in Home Assistant
Done, right?
Wrong.
graph LR
subgraph Expected Behavior
A[Turn off Bedroom Lights] --> B[Only Bedroom Lights Turn Off]
end
subgraph Actual Behavior
C[Turn off Bedroom Lights] --> D[Bedroom Lights Turn Off]
C --> E[Dishwasher Plug Turns Off!]
end
style E fill:#ff6b6b,stroke:#c0392b,color:#fff
The Investigation Begins
Step 1: Check the Automations
First suspect: a rogue automation. I searched through every automation in Home Assistant looking for any reference to dishwasher_plug. Nothing. I grepped through my configuration files. Still nothing.
The plug wasn’t mentioned anywhere in connection to the bedroom lights.
Step 2: Dive into MQTT Logs
Since zigbee2mqtt communicates via MQTT, I watched the message flow in real-time. Here’s what I captured when turning on the bedroom light group:
# 10:23:51 - Group command sent
Topic: zigbee2mqtt/ZG_Bedroom_Lights/set
Payload: {"state": "ON"}
# 10:23:51 - Bedroom lights respond (expected)
Topic: zigbee2mqtt/Bedside_Light_1
Payload: {"state": "ON", "brightness": 254, ...}
Topic: zigbee2mqtt/Bedside_Light_2
Payload: {"state": "ON", "brightness": 254, ...}
Topic: zigbee2mqtt/Bedroom_Ceiling_Light
Payload: {"state": "ON", "brightness": 254, ...}
# 10:23:53 - Wait, what? (2 seconds later!)
Topic: zigbee2mqtt/dishwasher_plug
Payload: {"state": "ON"}There it was! The dishwasher plug was receiving and responding to group commands - but it wasn’t in the group configuration.
Step 3: Verify the Group Configuration
I checked the zigbee2mqtt group configuration:
ZG_Bedroom_Lights:
friendly_name: ZG_Bedroom_Lights
devices:
- Bedside_Light_1
- Bedside_Light_2
- Bedroom_Ceiling_LightNo dishwasher_plug. The plug had been removed from the group weeks ago. So why was it still responding?
Understanding Zigbee Groups: The Key Insight
Here’s what I didn’t fully understand before this investigation:
Zigbee devices store their group memberships locally in their own firmware.
When you add a device to a group in zigbee2mqtt:
- z2m sends a Zigbee command to the device: “Add yourself to Group ID 1234”
- The device stores this in its non-volatile memory
- z2m updates its configuration file to track the membership
When you remove a device from a group:
- z2m sends a command: “Remove yourself from Group ID 1234”
- z2m updates its configuration file
- If the removal command doesn’t reach the device (network congestion, device asleep, interference), the device keeps the old group in memory
graph TD
subgraph Coordinator - zigbee2mqtt
A[Group Config: Lamps Only]
end
subgraph Smart Plug Firmware
B[Group Memory: Still in Lamps Group!]
end
subgraph Network
C[Group ON Broadcast]
end
A --> C
C --> B
B --> D[Plug responds to group command]
style B fill:#ff6b6b,stroke:#c0392b,color:#fff
style D fill:#ff6b6b,stroke:#c0392b,color:#fff
The configuration mismatch creates a “ghost” membership - zigbee2mqtt thinks the device is removed, but the device itself doesn’t know that.
Failed Solutions
Armed with this knowledge, I tried several approaches:
Attempt 1: Re-remove from Group via UI
I went to the zigbee2mqtt frontend and tried to remove the device from the group again. Since it wasn’t listed in the group, there was nothing to remove.
Result: Nothing changed.
Attempt 2: Device Unbind via MQTT
I tried the unbind command:
Topic: zigbee2mqtt/bridge/request/device/unbind
Payload: {"from": "dishwasher_plug", "to": "ZG_Bedroom_Lights"}Result: No effect. Unbind is for device-to-device bindings, not group memberships.
Attempt 3: Reconfigure the Device
In the zigbee2mqtt device page, I clicked “Reconfigure” hoping it would re-sync the device state.
Result: Still responding to group commands.
The Solution: Nuclear Group Removal
The fix was to use a specific MQTT command that tells the device to remove itself from ALL groups:
Topic: zigbee2mqtt/bridge/request/group/members/remove_all
Payload: {"device": "dishwasher_plug"}This command doesn’t just update zigbee2mqtt’s configuration - it sends a Zigbee command directly to the device’s firmware, clearing all stored group memberships.
Tip: You can find the MQTT Dev Console in the zigbee2mqtt frontend under Settings > Dev Console > MQTT.
The response confirmed success:
{
"data": {
"device": "dishwasher_plug",
"endpoint": "default"
},
"status": "ok"
}After running this command, the dishwasher plug stopped responding to bedroom light group commands. Mystery solved!
Applying the Fix: Step by Step
You have two options:
Option 1: zigbee2mqtt Dev Console
- Open the zigbee2mqtt frontend
- Go to Settings > MQTT
- In the Topic field, enter:
zigbee2mqtt/bridge/request/group/members/remove_all - In the Payload field, enter:
{"device": "your_device_friendly_name"} - Click Send
Option 2: Home Assistant Service Call
service: mqtt.publish
data:
topic: "zigbee2mqtt/bridge/request/group/members/remove_all"
payload: '{"device": "dishwasher_plug"}'Verification
Check the zigbee2mqtt logs for the response. You should see:
Removing endpoint '1' of device 'dishwasher_plug' from all groups
MQTT publish: topic 'zigbee2mqtt/bridge/response/group/members/remove_all',
payload '{"data":{"device":"dishwasher_plug","endpoint":"default"},"status":"ok"}'Prevention: How to Avoid Ghost Memberships
Based on this experience, here are some best practices:
1. Wait for Confirmation When Removing Devices
When you remove a device from a group in the zigbee2mqtt UI, check the logs for confirmation that the device acknowledged the removal. If you see errors or timeouts, the device may not have received the command.
2. Use remove_all Proactively
If you’re troubleshooting unexpected device behavior, running remove_all is a safe diagnostic step. It won’t harm devices that aren’t in any groups.
3. Keep Devices Awake During Group Operations
Battery-powered devices (like sensors) may miss group commands if they’re in sleep mode. For these devices, trigger them to wake up (open a door, press a button) before modifying group memberships.
4. Factory Reset When Repurposing Devices
This is the rookie mistake I made. When moving a device from one room/purpose to another, always factory reset it according to the manufacturer’s instructions. This clears:
- All stored group memberships
- Device-to-device bindings
- Any cached network information
It takes 30 seconds and saves hours of debugging.
Key Takeaways
| Concept | What I Learned |
|---|---|
| Group storage | Devices store group memberships locally in firmware, not on the coordinator |
| Config mismatch | zigbee2mqtt’s config can desync from actual device state |
| Unbind ≠ Group remove | unbind is for device-to-device bindings; groups need different commands |
| Timing matters | A 2-second delay suggested network-level behavior, not automation |
| The fix | group/members/remove_all clears all group memberships from device firmware |
Conclusion
What started as a puzzling “Why does the dishwasher turn off?” question turned into a deep dive into Zigbee group mechanics. The 2-second delay was the clue that pointed away from Home Assistant automations and toward Zigbee-level behavior.
If you ever find a device responding to commands it shouldn’t, remember: z2m’s configuration isn’t the whole truth. The device’s firmware has its own memory, and sometimes you need to speak directly to it.
Now if you’ll excuse me, I have some dishes to wash - with a smart plug that finally minds its own business.
Useful Resources:
