fix(cli): surface fatal [STARTUP] boot diagnostics without --log (#13314) - #13779
Merged
diegosouzapw merged 3 commits intoSep 16, 2026
Merged
Conversation
) ServerSupervisor's default (non --log) mode pipes the server child's stdout/stderr into an in-memory ring buffer that is only flushed to the real console when the child process exits or a readiness timeout fires. If the HTTP listener still comes up after a fatal `[STARTUP] Fatal: ...` boot diagnostic was already printed (e.g. the better-sqlite3/node:sqlite driver cascade failing hard), that line is captured but never shown -- every route then 500s with zero visible diagnostic anywhere. Generalizes the existing Android/Termux-specific force-print carve-out (isFatalInstrumentationHookFailure, #10028) to any `[STARTUP] Fatal:`- prefixed guard. Regression test: tests/unit/cli-supervisor-surfaces-fatal-startup-diagnostic-13314.test.ts
…4-windows-500-every-route-better
…tter (base-red fix #13747)
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…gosouzapw#13314) (diegosouzapw#13779) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #13314
This PR fixes the confirmed SIDE defect behind the "zero output anywhere" part of #13314:
ServerSupervisor's default (non--log) mode swallows a fatal[STARTUP] Fatal: ...bootdiagnostic until the child process exits — which never happens if the HTTP listener still comes
up after the fatal failure, so every route 500s with no visible diagnostic. It does not
resolve the reporter's underlying Windows-specific "why did the DB driver cascade fail" question,
which remains needs-info pending a
--logre-run from the reporter, and does not touch theseparate EADDRINUSE supervisor/server race already covered by open PR #12485.
Not covered here
this fix — the operator can now see the diagnostic without needing
--log).Root cause
bin/cli/runtime/processSupervisor.mjs::ServerSupervisor.start()spawns the server child withpiped (non-inherited) stdio whenever
--log/OMNIROUTE_SHOW_LOGis off (the default).bufferOutput()only pushes every line into an in-memory 50-line ring buffer; that buffer isflushed to the real console via
dumpCrashLog()only on process exit or a readiness-timeout.src/instrumentation-node.ts/src/instrumentation.tsalready print an unconditionalconsole.error("[STARTUP] Fatal: ...")for boot failures (#7773/#10171), but if the HTTP listenerstill comes up afterward (satisfying the readiness probe), the supervisor never sees an exit and
that fatal line is captured into the buffer but never shown. There was exactly one existing
carve-out from this rule (
isFatalInstrumentationHookFailure, an Android/Termux-specific stringmatch added for #10028) — not generalized to the
[STARTUP] Fatal:prefix used by every otherfatal boot guard.
Fix
bin/cli/utils/ensureAndroidCacheDir.mjs: addedisFatalStartupDiagnostic(text), matching the/^\[STARTUP\] Fatal:/mprefix already used consistently by every fatal boot guard.bin/cli/runtime/processSupervisor.mjs::bufferOutput(): alongside the existingisFatalInstrumentationHookFailurecheck, force-print the line toprocess.stderrimmediately(once per process run) when
isFatalStartupDiagnostic(text)matches — mirroring the existingAndroid carve-out pattern. The ring-buffer/
dumpCrashLog()behavior for everything else isunchanged; this is a narrow, additive carve-out.
Regression test
tests/unit/cli-supervisor-surfaces-fatal-startup-diagnostic-13314.test.tsRED (unfixed code):
GREEN (fixed code):
Gates run
npx eslint --suppressions-location config/quality/eslint-suppressions.json <changed files>— 0 errors (the two.mjsfiles are eslint-ignored by config, expected; the new test file is clean)node scripts/check/check-file-size.mjs— 1 pre-existing violation (open-sse/utils/stream.ts, untouched by this PR, confirmed present onorigin/release/v3.8.51) — no violation on files touched herenode scripts/check/check-complexity.mjs— OK, 2824 violations (baseline 3218)node scripts/check/check-cognitive-complexity.mjs— OKnode scripts/check/check-test-discovery.mjs— OK, new test discoveredtests/unit/cli-process-supervisor.test.ts,tests/unit/cli-process-supervisor-spawn-error-8091.test.ts,tests/unit/termux-android-cache-dir.test.ts,tests/unit/cli-serve-readiness-timeout-6321.test.ts) — all pass, no alignment neededExisting tests aligned
None — all pre-existing supervisor/Android-cache tests pass unmodified.