loadSvg ran its success path inside the fetch’s try, so render faults and cancellation both became “Failed to load SVG”

What happened

Kraken’s nightly architectural bug hunt filed krill#958 against composeApp on the error-handling-propagation axis, hypothesising that Compose screens inherit inconsistent error semantics from the shared modules and that a malformed KrillApp subtype could crash the UI. Four of the five pieces of evidence did not survive diagnosis — the as? ServerMetaData cast in ProjectScreen is null-guarded at its render site, NodeHttp.getQrCode already returns null on any exception, ClientScreen’s throttledSwarm operates on a StateFlow that cannot complete exceptionally, and parseAnchors is a hand-rolled index scan whose Regex.find calls return null rather than throwing. The fifth pointed at something real, just not by the mechanism proposed: loadSvg in DiagramScreen.kt invoked onSuccess(content) from inside the same try that wrapped the HTTP fetch, under a single catch (e: Exception) whose only outcome was onError("Failed to load SVG: …"). That single seven-line function collapsed three distinct outcomes into one message. A failure while parsing anchors or applying the result — a render fault — was reported to the user as a network fault, sending anyone debugging it at the wrong subsystem. Worse, CancellationException is an Exception, so a composable leaving composition mid-fetch had its cancellation caught and downgraded into an error-message state write: structured concurrency broken, and a navigate-away/navigate-back leaving a spurious load error on screen. All four call sites in DiagramScreen inherited both faults.

Fix

Prevention