Symptom

Kraken nightly scan flagged Lifecycle.kt’s inner scope.launch { piManager.initPins() } as unstructured, hypothesising a JVM crash risk. On inspection the JVM-crash claim was wrong (IO_SCOPE already carries SupervisorJob + CoroutineExceptionHandler), but two real issues were confirmed:

  1. A failure in piManager.initPins() produced only the generic “Uncaught exception in IO_SCOPE” log with no indication that GPIO was impacted — silent from an operator’s perspective.
  2. job.invokeOnCompletion always fired the startup-completion logic (node invocation, platformLogger.postLogs()) even when the outer startup job had failed, sending misleading telemetry and invoking the server node in a potentially broken state.

Root cause

The inner scope.launch block that runs initPins() had no try-catch, so any exception propagated to the scope’s generic handler. The invokeOnCompletion lambda did not inspect the cause parameter, so it ran unconditionally.

Fix

Prevention