Repository navigation
Stale NCP source route is never invalidated after SOURCE_ROUTE_FAILURE; end device unreachable until re-pair #772
Description
Summary
An end device changed parents. After that, the coordinator kept sending to it through the old source route. Every unicast came back with ROUTE_ERROR_SOURCE_ROUTE_FAILURE for the device's NWK. Uplink from the device kept working, but every downlink command timed out. Retries with FORCE_ROUTE_DISCOVERY failed the same way. Several many-to-one route refreshes (MTORRs) happened, and other routers answered them with route records, yet the stale entry stayed. The only thing that recovers the device is re-pairing it.
bellows receives the route errors, but handle_route_error() only logs them. Nothing invalidates the NCP's source-route entry, triggers a refresh for that destination, or falls back to plain AODV.
Environment
- Home Assistant 2026.10.4, ZHA 2.3.1, bellows 1.1.0, zigpy 2.3.0
- Home Assistant Connect ZBT-1, firmware 7.5.1.0 build 0 (20260224005823)
- zigpy
source_routingat its default (off). The host never callssetSourceRouteorxncp_set_manual_source_route(0 occurrences in the debug log), so the stale route comes from the NCP's own concentrator table.
Device
- Aqara H1 no-neutral switch
lumi.switch.b1laus01, EndDevice, NWK0x8F55 - Old parent:
0xFB91(IKEA VINDSTYRKA, router). New parent:0xD34C(IKEA TOFSMYGGA outdoor plug), according to the neighbor tables. zigbee.db,relays_v15for this device:0191FB. That is the last route record, still via0xFB91.
What the logs show
- A read of OnOff from the host results in a
sendUnicastto0x8F55. ThemessageSentHandlerto the first hop reportsSUCCESSorNO_APS_ACK. - About 0.3 s later:
incomingNetworkStatusHandler [ROUTE_ERROR_SOURCE_ROUTE_FAILURE: 11, 0x8F55]
incomingRouteErrorHandler {'status': SOURCE_ROUTE_FAILURE: 169, 'target': 0x8F55}
Processing route error: status=sl_Status.ZIGBEE_SOURCE_ROUTE_FAILURE, nwk=0x8F55
- zigpy retries with
APS_OPTION_RETRY|APS_OPTION_FORCE_ROUTE_DISCOVERY. The same route error comes back each time, and the request times out after 44 s. 10 of 11 reads failed this way over roughly 15 minutes, with 18 route errors logged for0x8F55. - MTORRs did go out. Route records arrived from other routers (
0xFB91,0x7C5A,0xD14F,0xF65Eand others) within seconds. - The device was then physically operated twice. Its reports arrived as
INCOMING_UNICASTfrom0x8F55(last hop LQI 100 to 104, RSSI -85), once about 10 s after a refresh burst. No route record for0x8F55arrived either time, so the stale entry was never replaced.
Expected
Once a source route to a destination keeps failing with SOURCE_ROUTE_FAILURE, it should stop being used. The stack or bellows should drop the entry, or let AODV route discovery take over, so the device becomes reachable through its new parent without re-pairing.
Notes
- The new parent apparently never sending a route record for its child (step 5) is what triggers this. That may be specific to the router or the device. But the coordinator has no recovery path once that happens.
- Also enable AODV route discovery on source-routed unicasts #719 (route discovery on source-routed unicasts) only applies when
source_routingis enabled, so it doesn't cover this case. Here route discovery was already requested, and was even forced, but the NCP's source-route table still took precedence. - A sanitized debug log excerpt is in the first comment. Device IEEE addresses are masked as
<ieee>.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Size
Area
Activity
tsmvp commentedon Oct 28, 2026
Debug log excerpt (bellows.zigbee.application, bellows.ezsp.protocol, zigpy.application at DEBUG), filtered to the relevant lines. It covers the sends to
0x8F55, the route errors, every route record received, and the incoming frames from0x8F55, including the two physical presses at 00:13:41 and 00:16:41. Device IEEE addresses are masked.Log (120 lines)
puddly commentedon Oct 28, 2026
The debug log doesn't contain much info here. If you haven't enabled source routing, it shouldn't be in use unless you enabled it and then disabled it again. What would be most helpful here is a traffic capture. Can you attach a traffic capture PCAP?
https://github.com/zigpy/ziggurat/blob/dev/crates/ziggurat-tools/src/bin/pcap_rekey.rs contains a tool to change the network key of a PCAP.