Mosquitto Without Persistence Took Every Zigbee Device Offline in Home Assistant
A broker restart dropped every retained MQTT discovery message, so Home Assistant marked all Zigbee2MQTT entities unavailable while the devices kept working. The mechanism, the fix, and the proof.
HomeLab, Smart home. Updated . 5 min read.
On 2026-09-20 every Zigbee entity in my Home Assistant went unavailable. The thermostat, the bedroom sensor, the plug, the entrance switch, all grayed out. Meanwhile the thermostat was reporting every 10 seconds, cooling at its setpoint, with a strong link. Nothing was wrong with Zigbee. The broker had forgotten what my devices were.
Home Assistant had just updated, so that was the obvious suspect. It wasn't the cause.
TL;DR: Mosquitto ran with no persistence line, so it kept retained messages in RAM. A broker restart deleted every retained MQTT discovery config. Zigbee2MQTT publishes discovery at its own start and had been up two days, so nothing put them back. Restarting Zigbee2MQTT fixed it in about 40 seconds. Three lines in mosquitto.conf fixed the cause.
What the timeline said
Two restarts, a few minutes apart, all times UTC:
| Time | Event |
|---|---|
| 14:17:58 | Mosquitto restarts. Zigbee2MQTT logs MQTT error: connect ECONNREFUSED <broker>:1883 and reconnects one second later |
| 14:21:25 | Home Assistant restarts |
| 15:18 | I notice every Zigbee entity is unavailable |
If you only look at Home Assistant, the update restart at 14:21 is the last event before the outage. The broker restart three and a half minutes earlier is the one that mattered, and the only trace of it on the Zigbee side is one reconnect line.
How MQTT discovery depends on retained messages
Home Assistant doesn't store Zigbee2MQTT devices the way it stores native integrations. It builds MQTT entities from discovery messages. Zigbee2MQTT publishes one config per entity to topics like:
homeassistant/<component>/<device>/<object>/config
Those messages are retained. The broker keeps the last message on each topic and hands it to every new subscriber. That's the whole trick: when Home Assistant starts and subscribes to homeassistant/#, the broker replays every config, and the entities appear. Nobody has to republish anything.
That works only while the broker still holds them. With no persistence, Mosquitto keeps the retained set in memory, and a restart wipes it.
So the chain was:
- Mosquitto restarts and comes back with an empty retained set.
- Zigbee2MQTT reconnects, but it publishes discovery only at its own start. It had been up two days, so it republished nothing.
- Home Assistant restarts, subscribes to discovery, and gets nothing.
- It marks all 30+ Zigbee2MQTT entities
restored: trueandunavailable.
The devices themselves were never affected. Zigbee2MQTT kept publishing live state the whole time: the AC thermostat every 10 seconds, system_mode: cool, setpoint 25.5, LQI 216-228. Home Assistant just had no entity to attach that state to.
One command for the diagnosis
The question was simple: does the broker still hold the discovery configs? Retained messages arrive the moment you subscribe, so a short subscribe answers it:
mosquitto_sub -u <user> -P <password> -t 'homeassistant/#' -W 5It returned 8 live state topics from HASS.Agent on my PC and zero retained /config topics. That's the signature. A healthy broker floods you with configs in the first second.
The quick fix
docker restart zigbee2mqttAbout 40 seconds. The coordinator keeps the network, so there's no re-pairing. On start, Zigbee2MQTT republished discovery, 73 retained configs came back, and all five paired devices returned in Home Assistant.
The same bug took out my PC sensors
Ten more entities from HASS.Agent on the PC (5 sensors, 5 buttons) were gone for the same reason. My first idea was to fake Home Assistant's birth message by publishing online to homeassistant/status by hand. HASS.Agent ignores that message, so it did nothing. Restarting HASS.Agent.exe republished all ten configs and they came back.
Two more entities from the HASS.Agent satellite service need that Windows service restarted, which needs an elevated shell. They wait for the next PC reboot.
Ruling out the rest
The unavailable count was 110 at the start. That number includes a lot that has nothing to do with the broker, so I went through it instead of assuming:
- six entities from a device that is no longer paired, stale registry rows (the bridge lists only 5 devices)
- a Wi-Fi plug that is off the network, a separate fault
- a smart lock that isn't mounted yet, expected
- about 30 TVs, casts, and phones that were simply off
The count went from 110, to 64 after the Zigbee2MQTT restart, to 55 after HASS.Agent.
The real fix: persistence
Restarting Zigbee2MQTT fixes the symptom. The cause is a broker that forgets on every restart. I turned persistence on the same hour. These are the lines in mosquitto.conf:
persistence true
persistence_location /mosquitto/data/
autosave_interval 60
persistence_location has to be a path that is mounted from the host, or the database dies with the container. autosave_interval 60 writes the in-memory state to mosquitto.db every 60 seconds, and Mosquitto also writes it on a clean shutdown.
There's a trap in turning it on. The restart that enables persistence loses the retained set one last time. The old process had persistence off, so it wrote nothing on shutdown, and the new process starts empty. Restart Zigbee2MQTT right after the broker, or you get the same outage you're fixing.
How I know it took
Two checks, both on the broker itself.
First, the startup log. Mosquitto now logs this at start, which it never did before:
Restored 0 retained messages
Zero is correct for that first boot, for the reason above. The line matters because it proves the broker is reading a persistence file at all.
Second, the file. data/mosquitto.db was 47 bytes, dated May 2025. So the file existed, but nothing had written to it in over a year. After the restart it was 396 KB, written within the minute. That's the autosave writing the retained discovery set to disk.
Why it hadn't bitten before
For a while, a nightly appdata backup stopped and started mosquitto, Zigbee2MQTT, and Home Assistant together. I stopped those container restarts on 2026-09-05. My guess is that the nightly restarts hid this bug, because Zigbee2MQTT restarted right after the broker and republished discovery every time. Once the broker could restart on its own, nothing republished discovery.
The rule I wrote down in my notes: after any mosquitto restart that loses retained messages, restart zigbee2mqtt. With persistence on, that should now be rare. The broker keeps the configs across a restart, and Home Assistant finds them the next time it subscribes.
Questions
- Why did all my Zigbee2MQTT entities go unavailable after Mosquitto restarted?
- Home Assistant builds MQTT entities from retained discovery messages on homeassistant/.../config topics. Without persistence, Mosquitto keeps retained messages in RAM, so a restart deletes them. If Zigbee2MQTT does not republish discovery, Home Assistant has no configs and shows the entities as unavailable.
- How do I turn on persistence in Mosquitto?
- Add persistence true, persistence_location pointing at a mounted data folder, and an autosave_interval to mosquitto.conf, then restart the broker. Check that the log shows a Restored retained messages line at startup and that mosquitto.db grows.
- How do I check whether my broker still holds the discovery configs?
- Run mosquitto_sub -t 'homeassistant/#' -W 5 against the broker. Retained config topics arrive right away. If you see only live state topics and no /config topics, the retained set is gone.
- Do I need to restart Zigbee2MQTT after enabling Mosquitto persistence?
- Yes. The restart that turns persistence on still loses the old retained set, because the old process had nothing to save. Restart Zigbee2MQTT right after, so it republishes discovery into the new persistent store.