From f10c53bdfbeebb4daccb3fb6c99562972946ce3d Mon Sep 17 00:00:00 2001 From: Craig Allen Date: Tue, 10 Mar 2026 11:45:20 +0100 Subject: [PATCH] Fix OTBR migration script connecting to adapter when no settings to migrate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The migrate_otbr_settings.py script unconditionally calls get_adapter_hardware_addr() before checking whether any .data files exist that actually need migrating. On some dongles (ZBT-1 with firmware 2.7.2.0, Sonoff Dongle Lite MG21) this causes a TimeoutError or AssertionError because the adapter resets its USB connection in response to the Spinel RESET command. The script exits with code 1, preventing otbr-agent from ever starting — even on a fresh install with no prior configuration. Fix: scan the data directory for .data files first. If none are found, exit cleanly without touching the adapter. Only connect to the adapter if there is something to migrate. Fixes #4475 --- .../usr/local/bin/migrate_otbr_settings.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/openthread_border_router/rootfs/usr/local/bin/migrate_otbr_settings.py b/openthread_border_router/rootfs/usr/local/bin/migrate_otbr_settings.py index c31043ce0..4a9315a00 100755 --- a/openthread_border_router/rootfs/usr/local/bin/migrate_otbr_settings.py +++ b/openthread_border_router/rootfs/usr/local/bin/migrate_otbr_settings.py @@ -152,14 +152,10 @@ async def main() -> None: if flow_control == "none": flow_control = None - # First, read the hardware address of the new adapter - hwaddr = await get_adapter_hardware_addr( - port=args.adapter, - baudrate=args.baudrate, - flow_control=flow_control, - ) - - # Then, look at existing settings + # First, look at existing settings before touching the adapter. + # If there is nothing to migrate, skip the adapter connection entirely. + # This avoids a TimeoutError / AssertionError on dongles that reset their + # USB connection in response to a Spinel RESET (issue #4475). all_settings = [] for settings_path in args.data_dir.glob("*.data"): @@ -184,6 +180,13 @@ async def main() -> None: print("No existing settings files found, skipping") return + # Only connect to the adapter if there are settings files that need migrating + hwaddr = await get_adapter_hardware_addr( + port=args.adapter, + baudrate=args.baudrate, + flow_control=flow_control, + ) + most_recent_settings_info = sorted(all_settings, reverse=True)[0] most_recent_settings_path = most_recent_settings_info[1] most_recent_settings = most_recent_settings_info[2]