Repository navigation
Runtime Host candidate election storms and permanent unavailability once stored transcripts exceed the 45s ready window #5843
Description
Activity
- added a commit that references this issue
on Sep 30, 2026 take
Status on #5843: my #5922 covers the permanent-unavailability half and #5845 shipped the loser diagnostic. One measured gap remains on main: connect-or-spawn.ts sets DEFAULT_ELECTION_DEADLINE_MS = 75_000 (line 75) while the desktop candidate waits readyTimeoutMs ?? 45_000 (line 514), and launch_election_lost is classified permanent (candidate-startup-failure.ts line 27). Should those two windows be one value? Happy to align them if 45s was not deliberate.
Dug into the history before answering: the 45s is not deliberate.
readyTimeoutMs: input.electionDeadlineMs ?? 45_000(runtime-host-desktop-candidate.ts:514) came in with the parity sweep #2216 as a plain fallback — no alignment argument anywhere in that change. The 75s side, by contrast, documents its reasoning in place (connect-or-spawn.ts:72-74): the Windows named-pipe ACL helper's fail-closed ceiling is 60s, plus room for election and connection bookkeeping.So please align — and from the #5843 fault path the mismatch is not neutral: with a 45s manager-side window under a 75s election window, the manager can declare a candidate dead while the election it lost is still inside its legitimate window. That is exactly the replace-and-reshuffle amplifier we measured (large-store winner initialization exceeding 45s → manager swaps → every replacement loses again). One concrete suggestion: rather than bumping 45→75 as a second magic number, have the desktop fallback reference the same constant/env channel the client already honors (
MAKA_RUNTIME_HOST_ELECTION_DEADLINE_MS), so the two windows can't drift apart again.On
launch_election_lostbeing classified permanent (candidate-startup-failure.ts:27): per-candidate that reads correct to me — a loser exits so the manager can spawn a fresh attempt — and the storm was caused by the window mismatch, not the classification. With the windows aligned I'd leave the classification alone, but that's a maintainer call.- added a commit that references this issue
on Oct 4, 2026 Aligned in 000b70e on #5922. The Desktop fallback now resolves the caller value, then MAKA_RUNTIME_HOST_ELECTION_DEADLINE_MS, then DEFAULT_ELECTION_DEADLINE_MS, which the client exports. One constant, so the windows cannot drift again. The new desktop test fails 45000 !== 75000 without the fix; that suite is 27/27. Leaving launch_election_lost permanent, as you argued. A second 45s default sits at host-profile.ts:595, untouched.
- added a commit that references this issue
on Oct 10, 2026
Summary
When the stored transcript volume exceeds roughly 210-360MiB, the Runtime Host candidate startup exceeds its 45-second ready window, and every replacement candidate then loses the launch election and exits - the Host never becomes available, and the desktop shows
RuntimeHostHandlerUnavailableErrorfor every operation. 13+ consecutive candidate exits ({code: 2, signal: null}) were observed on one attempt.Mechanism (all points verified in source)
process.exit(2)fires only on the election loser path (packages/runtime-host/src/candidate-entry.ts:107,result.kind === 'loser'aftertryAcquireRuntimeHostLaunchfails to take the launch lease,server/candidate.ts:84). Exit 2 is therefore not a crash - it is the documented loser exit, taken silently (no startup diagnostic is written, so nothing lands on disk).electionDeadlineMs ?? 45_000for the candidate to become ready (apps/desktop/src/main/runtime-host-desktop-candidate.ts:514).Scale bisection (same fixture family, single-machine)
The threshold sits somewhere in 210-360MiB of total stored transcript volume.
Related
Fix directions (for discussion)
Repro recipe
seed-helpers.tswithLARGE_HISTORY_TURN_COUNTS(12,000 / 4,000 / 4,000 turns x 18KiB replies) through the desktop candidate chain; archived spec, logs (13x exit-2 + handler-unavailable), and the bisect runs are available.