fix(api): describe a failed snapshot build by its cause, not its tail (DEV-2570) - #239
Merged
Merged
Conversation
A snapshot install/build that failed was described with `execTail` — the last 800/1200 characters of stderr + stdout. A tail cuts at the front, so the first line of the message was whatever the tool printed last: pnpm's progress counter (Sentry DEMOS-1W) or the middle of its self-update box (DEMOS-1Y). Sentry titles an issue from that first line, so neither issue named the failure, and because the message was multi-line the browser SDK fed lines 2..n to its stack-frame regexes and invented the culprit `│ Changelog: (v/11.22)`. DEV-2533 already solved this for the Tier-2 boot log. Rather than a second copy of those regexes, move the rule set to `packages/runtime/src/failure-log.ts`: `bootFailureDetail` stays as a thin wrapper with the boot defaults (and the same export `container-boot-failure.test.mjs` imports), and a new `execFailureDetail` handles the builder's two streams. Its tiers run across the streams rather than within a concatenation of them — an announced cause on either stream outranks a merely mentioned one on either — because pnpm keeps counting on stdout after diagnosing on stderr, while vite/ng/next report real errors on stdout and leave deprecation noise on stderr. The window, the empty-output wording, and the byte cap on the kept log become options. `runBuild` now throws `BuildFailure`: a one-line message, with the output kept apart in `log` and the machine code in `code`, mirroring `ContainerBootFailure`. The route catch-all reports it under `context: snapshot-build`, fingerprinted by phase and code so one defect stays one issue, with the log as an `extra`. Rollout: the message changes, so grouping changes. DEMOS-1W and DEMOS-1Y stop receiving events and correctly titled issues appear in their place. DEV-2570 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0d2d246. Configure here.
… reset from erasing one Two defects found reviewing the picker against real build output. `vite build` announces its failure with a section label — `error during build:` — and puts the error on the next line. The announcing tier stopped on the label, so every vite failure described itself as `build failed: error during build:`: no package, no import, nothing. It is the build command for nearly every framework in the catalog, so that was the common path rather than an edge case. A cause line that ends in a colon now takes the line under it, joined rather than replaced — the label says which tool failed, the line under it says what did. `\x1b[nG` at the END of a line resets nothing, since there is no next frame on that line to keep, but `LINE_RESET` treated it as one and the slice then deleted the line whole. A log that was one such line — `ERR_PNPM_OUTDATED_LOCKFILE …\x1b[0G` — came out as "no output", losing the cause and, because the report site only attaches a non-empty log, the `buildLog` extra with it. Trailing resets are dropped before the last-frame-wins slice; a redraw mid-line still collapses as before. The `ELIFECYCLE`-on-stdout fixture went with them: `runBuild` execs the build binary off `node_modules/.bin` rather than an npm script, so pnpm's epilogue never appears on that stream. It is now a real vite log, which is what surfaced the first defect. DEV-2570 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ict the other The tail cap keeps the END of the join, and `execFailureDetail` joined stdout then stderr — so a stream of deprecation warnings long enough to fill the budget on its own dropped stdout whole. Measured at the builder's 4000-character cap: 60 lines of `DeprecationWarning` on stderr, and the vite line the cause had just been picked from was absent from `buildLog`, leaving an extra that explained nothing (Bugbot, PR #239). Each stream is now capped in its own right, and a stream that does not need its half lends the remainder to the other so a quiet stderr does not cost stdout half the budget for nothing. DEV-2570 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

Problem
A snapshot install/build that failed was described with
execTail— the last 800/1200 characters ofstderr + stdout. A tail cuts at the front, so the first line of the message was whatever the tool printed last: pnpm's progress counter (DEMOS-1W) or the middle of its self-update box (DEMOS-1Y). Sentry titles an issue from that first line, so neither issue named the failure — and because the message was multi-line, the browser SDK fed lines 2..n to its stack-frame regexes and invented the culprit│ Changelog: (v/11.22).One failure, two mistitled issues: the Worker files one from the catch-all in
index.ts, and the browser files another becausedescribeApiFailurerelaysbody.errorverbatim into anApiError.Fix
DEV-2533 already solved this for the Tier-2 boot log. Rather than a second copy of those regexes, the rule set moves to
packages/runtime/src/failure-log.ts:bootFailureDetailstays as a thin wrapper with the boot defaults (and the same exportcontainer-boot-failure.test.mjsimports), and a newexecFailureDetailhandles the builder's two streams.Its tiers run across the streams rather than within a concatenation of them — an announced cause on either stream outranks a merely mentioned one on either — because pnpm keeps counting on stdout after diagnosing on stderr, while vite/ng/next report real errors on stdout and leave deprecation noise on stderr. The window, the empty-output wording, and the byte cap on the kept log became options; the boot path keeps its previous behaviour exactly (uncapped tail — capping here would measure the cleaned, redacted string rather than the 2500 bytes the status route already tailed).
runBuildnow throwsBuildFailure: a one-line message, with the output kept apart inlogand the machine code incode, mirroringContainerBootFailure. The route catch-all reports it undercontext: snapshot-build, fingerprinted by phase and code so one defect stays one issue, with the log as anextra.Before / after, on the DEMOS-1W fixture:
Rollout
The message changes, so grouping changes: DEMOS-1W and DEMOS-1Y stop receiving events and correctly titled issues appear in their place. Expected, not a regression — resolve both once the successors show up.
Out of scope
The underlying
handsontable@13106install failure is DEMOS-1X / DEV-2565. The duplicate client-side report also stays:describeApiFailurefiles an issue for every 500, and the single-line message makes that issue readable, which is what this ticket is about; suppressing the duplicate is a separate change.Verification
pnpm test— 767 tests, 765 pass, 0 fail, 2 pre-existing todo. 16 new inpipeline/failure-log.test.mjs, each verified red against the old tail rule;container-boot-failure.test.mjspasses unedited, which is the regression guard for the extraction.pnpm -r run typecheck— 4 projects clean.wrangler deploy --dry-run— the Worker bundles the new@handsontable/demo-runtime/failure-logsubpath.ERR_PNPM_*-titled issue). Needs a deploy.🤖 Generated with Claude Code
Note
Cursor Bugbot is generating a summary for commit 0d2d246. Configure here.