Symptom

Clicking an unconfigured Server.Pin (pinNumber == 0) opened the edit screen, flashed a small spinner for ~1s, then collapsed to a blank screen. No GPIO header view, no error, no retry — the user had no way to recover except to back out of the editor and start over.

Root cause

EditPin had two branches: pins.empty && error.empty (spinner + load) and pins.notEmpty (header view or edit fields). When nodeHttp.getGpioHeader returned an empty list (server isn’t a Pi, krill-pi4j is unreachable, response fails to deserialize), the load path set error = "..." but no branch matched pins.empty && error.notEmpty, so the composable simply emitted nothing.

Fix

Replace the if/else-if pair with a four-way when (loading / empty-with-error / configured-pin / pick-pin) so every state renders something. Hoist the LaunchedEffect out of the conditional, key it on host.id and a retry counter, and add a Retry button on the empty-state branch so a transient failure is self-recoverable.

Prevention

Compose UI rendering is hard to assert in unit tests on KMP, so no regression test was added — the only way to catch a “no branch matches → nothing renders” regression today is reviewer eyeballs. Going forward, prefer when {…} over chained if/else if in Composables: the compiler then can’t help, but it’s visually obvious when an else branch is missing.