The defect
After any bridge-node restart the node comes online with zero child endpoints and stays that way until the plugin connects and attaches. Measured on jarvis after a full reboot:
10:59:30.177 indigo-matter-bridge is online <- aggregator EMPTY
10:59:53.198 Client attached, reconciling 4 endpoint(s)
10:59:53.773 Endpoint 287885105 added as number 3
...
23 seconds advertising as a bridge with no accessories. Apple reconnects inside that window, reads an empty PartsList, and concludes every accessory has gone. When they reappear it treats them as new arrivals: assigned to the bridge's own room, with metadata the user can no longer edit ("cannot change settings").
Why this is the root cause
It is the only theory consistent with every observation:
| Observation |
Explained by |
| Rooms broke after the E5 plugin/node upgrade |
node restart → empty window |
| A fresh unpair + re-pair fixed them |
accessories present from the moment of pairing |
| Rooms broke again after a full reboot |
node restart → empty window |
| A newly exported device was roomable |
added while the node was up; never vanished |
| …but broke once un-exported and re-exported |
Apple saw that one endpoint vanish and return |
Three earlier theories were tested and disproved (no-Matter-traffic; un-export identity reuse; configurationVersion reset — matter.js does persist and restore it). This one is measured, not inferred.
Impact
Every restart of the bridge node — reboot, plugin upgrade, agent restart, crash recovery — costs the user their room assignments for all exported accessories, and they cannot be set again without a full unpair/re-pair cycle. That is the single most user-visible defect in the export feature.
Fix
The node must never serve an empty aggregator. It should reconstruct its last-known endpoint set at startup, independently of the plugin, with reachable: false until the plugin attaches and confirms real state. Apple then sees a bridge whose accessories were briefly unreachable — a state it handles routinely — rather than a bridge that lost everything.
Implementation notes:
endpoint-map.json already persists identity (uniqueId → endpoint number) and already survives factoryReset. It needs the role and label too so an endpoint can be rebuilt without the plugin.
- Restore before
server.start() so the node is never online-and-empty.
- The plugin's
attach remains authoritative: it reconciles the restored set, which is what removes anything genuinely un-exported while the plugin was away.
- Watch the interaction with §3.1's mass-removal guard — a restored set the plugin then legitimately empties must still be refused without
intent: replace_all.
reachable: false on restore also makes XAC8 honest: accessories show as unavailable until the plugin is actually driving them.
Related
The defect
After any bridge-node restart the node comes online with zero child endpoints and stays that way until the plugin connects and attaches. Measured on jarvis after a full reboot:
23 seconds advertising as a bridge with no accessories. Apple reconnects inside that window, reads an empty
PartsList, and concludes every accessory has gone. When they reappear it treats them as new arrivals: assigned to the bridge's own room, with metadata the user can no longer edit ("cannot change settings").Why this is the root cause
It is the only theory consistent with every observation:
Three earlier theories were tested and disproved (no-Matter-traffic; un-export identity reuse;
configurationVersionreset — matter.js does persist and restore it). This one is measured, not inferred.Impact
Every restart of the bridge node — reboot, plugin upgrade, agent restart, crash recovery — costs the user their room assignments for all exported accessories, and they cannot be set again without a full unpair/re-pair cycle. That is the single most user-visible defect in the export feature.
Fix
The node must never serve an empty aggregator. It should reconstruct its last-known endpoint set at startup, independently of the plugin, with
reachable: falseuntil the plugin attaches and confirms real state. Apple then sees a bridge whose accessories were briefly unreachable — a state it handles routinely — rather than a bridge that lost everything.Implementation notes:
endpoint-map.jsonalready persists identity (uniqueId→ endpoint number) and already survivesfactoryReset. It needs the role and label too so an endpoint can be rebuilt without the plugin.server.start()so the node is never online-and-empty.attachremains authoritative: it reconciles the restored set, which is what removes anything genuinely un-exported while the plugin was away.intent: replace_all.reachable: falseon restore also makes XAC8 honest: accessories show as unavailable until the plugin is actually driving them.Related
docs/INSTALL.md's troubleshooting row for room edits should point here once fixed.