Docs Reference

Error handling

How LumaSync recovers from render faults — the global ErrorBoundary, the fallback card, the actions available from it, and the macOS lifecycle shutdown path.

From v1.4, LumaSync wraps every React root with a global ErrorBoundary. When a render fault bubbles out of the component tree, you get a localised fallback card — not a blank tray window, not a silent crash. The app keeps running; only the broken panel is replaced with the card.

The fallback card

Shows:

  • A short, localised headline (“LumaSync ran into a problem rendering this panel.”)
  • The underlying error message (not the stack trace)
  • An anonymised fingerprint of the error, used to correlate with the log file

Three actions sit at the bottom of the card:

  • Show logs — opens the platform log directory via open_log_dir. The full stack trace sits in the most recent log file, correlated by the card’s fingerprint. See Notifications → open_log_dir.
  • Restart — terminates and relaunches the app via tauri-plugin-process. State in ~/.config/lumasync/app.json persists across restart; in-memory session data (current mode, frame queue) is discarded.
  • Copy error — copies the error message + fingerprint to the clipboard, ready to paste into a GitHub issue or Discussion thread. Does not copy your config, credentials, or the log body — those stay on disk.

What ErrorBoundary catches

  • Render-time exceptions in React components (the common case)
  • Effect-callback exceptions that synchronously propagate during render
  • Lifecycle errors in class components (none ship today, but the boundary handles them anyway)

What it does NOT catch

  • Backend worker panics — the Rust / Tauri side. Those are logged by the Rust tracing layer and surface as a different UI state: the pipeline halts, status pills go red, no fallback card appears. Check the log file for the panic line.
  • Unhandled promise rejections outside React’s lifecycle — a background fetch that rejects without a .catch lands in the log but does not trip the boundary.
  • WebView hard crashes (rare) — those terminate the Tauri window entirely; macOS / Windows surface an OS-level crash dialog.

Filing a good issue

If the fallback card appears, attach:

  1. The Copy error clipboard contents (message + fingerprint)
  2. The most recent log file from Show logs (review first — it contains your bridge IP and local paths)
  3. What you were doing when it fired (opened Settings, switched modes, etc.)

Together those three let a maintainer reproduce in the dev console without asking follow-up questions.

macOS lifecycle hardening (v1.5.2)

The macOS shutdown path was previously fragile: Cmd+Q, the tray Quit menu, and Ctrl+C in dev each had their own teardown logic, with subtle ordering differences that could leak file descriptors, the single-instance lock socket, or the Hue DTLS sender thread.

From v1.5.2 all three paths converge on a single kick_off_shutdown_and_die Rust function gated by an atomic SHUTDOWN_FIRED flag. Two follow-ups landed alongside the unification:

  • The watchdog’s std::process::exit(0) previously bypassed Tauri plugin destroy() callbacks, which left tauri-plugin-single-instance’s /tmp/com_lumasync_app_si.sock socket on disk. The next dev launch detected the stale socket and exited within ~50 ms. The plugin is now #[cfg(not(debug_assertions))]-gated to release builds only, so dev launches don’t touch the socket and don’t leak it.
  • stop_hue_stream could block for up to 8 s under a worst-case combination of reqwest timeout (5 s) plus a DTLS sender Condvar (3 s), blowing through the 4 s watchdog budget. The call is now detached onto a worker thread and abandoned after 1.5 s — safe because the bridge times out the entertainment session server-side regardless.

End result: Cmd+Q closes the app cleanly within the watchdog budget every time, and dev rebuilds no longer fail with single-instance-lock hangs.

macOS launch crash on 1.5.2 (fixed in v1.5.3)

Every 1.5.2 macOS install on a machine without Xcode crashed immediately on launch with dyld: Library not loaded: @rpath/libswift_Concurrency.dylib. The screen-capture stack’s Swift runtime was being linked against a build-machine toolchain path instead of the system Swift concurrency library. v1.5.3 pins the Swift runtime deployment target across all build paths so it links the library that ships with macOS, and a release-pipeline guard now blocks any future binary that would regress this. Fix: update to v1.5.3 or later.

Shutdown hardening, continued (v1.5.3)

v1.5.3 hardens the same teardown path further:

  • The lighting-worker teardown step is now time-bounded to 1.5 s, so a slow worker join can no longer starve the Hue entertainment-mode deactivate under the shutdown watchdog (previously this risked leaving the bridge with a phantom active streamer).
  • On Windows, screen-capture teardown is detached onto its own thread, so switching lighting modes no longer briefly freezes the UI while the capture stack tears down.

Type to search. Up and down arrows to navigate, Enter to open.