fix(ble): don't throw from long-session health snapshot on Linux - #834
Conversation
getLongSessionHealthSnapshot() called the throwing getSession() unconditionally. On Linux, Noble is never initialized (Web Bluetooth is used in the renderer instead), so the sessions map stays empty for the app's whole lifetime. Once the hourly main-process health-log timer's 24h uptime gate opened, the first tick threw an uncaught "Unknown noble session: meshtastic" in the main process, surfaced to the user as the "Mesh-Client — Unexpected Error" dialog after about a day of uptime. Guard sessionDetail() the same way disconnectAll() and stopAllScanning() already guard for Linux, returning a benign not-initialized snapshot instead of throwing. Extract the shared isLinuxNotInitialized() check that guard duplicated across all three call sites into one private helper.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: QUIET Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe Noble BLE manager centralizes detection of uninitialized Linux sessions. Health snapshots return disconnected details without accessing unavailable session state, and scanning shutdown and disconnection cleanup use the shared check. Regression tests cover these paths. ChangesLinux Noble initialization handling
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
On Linux, after mesh-client had been running continuously for a bit over 24 hours, users could hit an "Mesh-Client — Unexpected Error" dialog:
Diagnosed from a user-supplied support bundle: the crash fired at exactly 24h 9s of main-process uptime, matching the hourly
long-session healthtimer insrc/main/index.tsthat only executes its body onceprocess.uptime()crosses the 24h threshold.Root cause
NobleBleManager.getLongSessionHealthSnapshot()called the throwinggetSession()unconditionally for both themeshtasticandmeshcoresessions. On Linux, Noble is never initialized (Web Bluetooth is used in the renderer instead) — the constructor returns early before populating thesessionsmap, so it stays empty for the app's entire lifetime. The first time the 24h-gated health-log timer actually ran its body, the lookup threw, and since it's an uncaught exception in the main process, the globaluncaughtExceptionhandler surfaced it as a user-facing error dialog (the app itself did not crash/quit — traffic continued normally afterward).Fix
Guard the session lookup the same way
disconnectAll()andstopAllScanning()already guard for Linux, returning a benign "not initialized" snapshot instead of throwing. Extracted the sharedsessions.size === 0check (which was about to be triplicated) into one privateisLinuxNotInitialized()helper used by all three call sites.Testing
noble-ble-manager.test.ts(source-contract style, matching this file's established pattern for testing a class that wraps the native@stoprocent/noblemodule) verifying the guard is present and that no inlinesessions.size === 0checks remain outside the shared helper.pnpm run typecheck,pnpm exec eslinton changed files, and the fullmainVitest project (200 files / 2223 tests) all pass.noble-ble-manager.behavior.test.ts, 53 tests).Summary by CodeRabbit
Bug Fixes
Tests