Same class as #218, different route — and this one drives what the user sees, so it is how the
console comes to lie about connectivity.
What happens
GET /v1/instances/:instanceId/runtime/status (routes/instances.ts:729) resolves the runner with
requireRuntime → getRuntime, which reads the single default row:
SELECT * FROM instance_runtimes WHERE instance_id = ?1 AND user_id = ?2 -- instances-runtime.ts:621
Per-node truth lives in a different table (instance_runtime_nodes, getRuntimeNode:636). The
default row is overwritten by the newest pags up and is never cleared on disconnect — the
docstring on requireLiveRuntime says so, and says anything that dispatches must use the live,
pin-aware resolver instead.
The route then does:
const relayIsConnected = await relayConnected(c.env, instanceId, runtime.runner_node); // :754
return c.json({ …, relay: { connected: relayIsConnected, runnerNode: runtime.runner_node } });
So on a multi-machine account it reports the relay state of whichever machine registered last,
not the machine that is live or the one the instance is pinned to.
Why it matters
This response is the console's connectivity signal in two places:
pages/InstanceDetail.tsx:186 — the header dot: setRunnerOnline(d.relay?.connected === true).
No fallback. Wrong default row ⇒ the dot is simply wrong.
tabs/SettingsTab.tsx:163 — agentOnline = relayInfo?.connected === true || pinnedDetail?.connected === true.
The pinnedDetail fallback partially papers over it, which is likely why this hasn't been
noticed: Settings can recover where the header cannot.
It also persists the wrong verdict: updateRuntimeStatus(…, effective) at :753 writes a
status derived from probing the wrong node onto the default row, which other callers then read.
Failure shape: pags up on the laptop, then on the desktop (default row → desktop). Desktop
sleeps, laptop still serving. Header dot reads the desktop's dead relay and says offline while
every runner tool works. Reverse the order and it claims online against a machine that is gone.
Expected
Resolve the same way dispatch does — live, pin-aware (getBoundRunnerConn / requireLiveRuntime)
— and report the node it actually resolved, so relay.runnerNode names the machine the verdict is
about. A status endpoint that disagrees with the routing layer is worse than no status endpoint.
Verification
- Two registered nodes, default row stale, live socket on the other:
/runtime/status reports
connected, and relay.runnerNode names the LIVE machine.
- The header dot and Settings agree with each other and with
coding_diagnostics.
- Probing does not write an offline status derived from a node that isn't the live one.
Same class as #218, different route — and this one drives what the user sees, so it is how the
console comes to lie about connectivity.
What happens
GET /v1/instances/:instanceId/runtime/status(routes/instances.ts:729) resolves the runner withrequireRuntime→getRuntime, which reads the single default row:Per-node truth lives in a different table (
instance_runtime_nodes,getRuntimeNode:636). Thedefault row is overwritten by the newest
pags upand is never cleared on disconnect — thedocstring on
requireLiveRuntimesays so, and says anything that dispatches must use the live,pin-aware resolver instead.
The route then does:
So on a multi-machine account it reports the relay state of whichever machine registered last,
not the machine that is live or the one the instance is pinned to.
Why it matters
This response is the console's connectivity signal in two places:
pages/InstanceDetail.tsx:186— the header dot:setRunnerOnline(d.relay?.connected === true).No fallback. Wrong default row ⇒ the dot is simply wrong.
tabs/SettingsTab.tsx:163—agentOnline = relayInfo?.connected === true || pinnedDetail?.connected === true.The
pinnedDetailfallback partially papers over it, which is likely why this hasn't beennoticed: Settings can recover where the header cannot.
It also persists the wrong verdict:
updateRuntimeStatus(…, effective)at:753writes astatus derived from probing the wrong node onto the default row, which other callers then read.
Failure shape:
pags upon the laptop, then on the desktop (default row → desktop). Desktopsleeps, laptop still serving. Header dot reads the desktop's dead relay and says offline while
every runner tool works. Reverse the order and it claims online against a machine that is gone.
Expected
Resolve the same way dispatch does — live, pin-aware (
getBoundRunnerConn/requireLiveRuntime)— and report the node it actually resolved, so
relay.runnerNodenames the machine the verdict isabout. A status endpoint that disagrees with the routing layer is worse than no status endpoint.
Verification
/runtime/statusreportsconnected, and
relay.runnerNodenames the LIVE machine.coding_diagnostics.