Many server node processors ran their work in a bare scope.launch { … } with no
try/catch (e.g. ServerTriggerProcessor, ServerDataPointProcessor) or caught exceptions
only to log them (the webhook processors). An uncaught exception escaped to the
coroutine scope’s CoroutineExceptionHandler, which only logged — so the node never
entered NodeState.ERROR, nothing was emitted over SSE, and clients showed a node that
looked fine while it had silently failed. Even when an error was recorded, the only
place it surfaced was a single editor row gated to EDIT mode.
launchProcessing(nodeManager, node) { … } (async) and
ServerNodeManager.runProcessing(node) { … } (sync) in
server/src/jvmMain/kotlin/krill/zone/server/ProcessingScope.kt. Both funnel any
uncaught failure into nodeManager.failed(node, …), rethrow CancellationException,
and contain any secondary failure raised while reporting (so a captured error can
never re-escape).ServerTriggerProcessor,
ServerDataPointProcessor, ServerLogicGateProcessor, ServerGraphProcessor,
ServerWebHookOutboundProcessor, ServerWebHookInboundProcessor, and
ServerServerProcessor (which also gained a nodeManager constructor dependency).
The webhook outbound processor now acts on the per-method Boolean result it used to
discard, so a non-2xx response also reaches ERROR.NodeChipScaffold (wrapped by every chip) now reads reactive node state and renders
meta.error’s first line, truncated, in colorScheme.error.ErrorMessageRow() from EDIT mode so the full error shows at the editor
bottom across all tabs.process() body must never run in a bare scope.launch or a
catch-and-log block. Use launchProcessing / runProcessing so a failure always
becomes NodeState.ERROR — the safe path is now the default path.ProcessingScopeTest, which asserts a thrown error
reaches ERROR + meta.error and is emitted over the node-update (SSE) pipeline.setErrorState no-ops for a node the manager doesn’t yet know, so a failure during a
node’s initial registration is still dropped — keep node registration ahead of any
fallible processing.scope.launch processors not touched here (Lambda, Pin, Cron, Serial,
LLM, Backup, Mqtt, Compute, SMTP, Calculation, TaskList, DataProcessor) should be
migrated opportunistically; several already carry correct try/catch + failed(). Audit
with: grep -rln "scope.launch" server/src/jvmMain/.../krillapp and check each for a
failure path.