Skip to content

fix(probe): report the real compile error on the browser tier - #1325

Merged
tenphi merged 1 commit into
mainfrom
fix/probe-browser-compile-error
Aug 17, 2026
Merged

fix(probe): report the real compile error on the browser tier#1325
tenphi merged 1 commit into
mainfrom
fix/probe-browser-compile-error

Conversation

@tenphi

@tenphi tenphi commented Aug 17, 2026

Copy link
Copy Markdown
Member

Describe changes

A snippet that failed to compile under pnpm probe:browser reported this, and nothing else:

Snippet failed to compile:

Failed to fetch dynamically imported module: http://localhost:63315/.probe/1786981288954-16512/snippet.tsx?import

A network fault, against a URL nobody typed — for what was a parse error on line 2 of the snippet. The jsdom tier reported the same typo properly, so the two tiers disagreed on the slower one: the tier you are least willing to re-run blind. This is the failure docs/rules/probe.md says the tool refuses to commit ("an error about a snippet nobody wrote"), so it is a bug in the probe rather than a rough edge.

Same broken snippet, before and after:

Failed to fetch dynamically imported module: http://localhost:63315/.probe/…/snippet.tsx?import
Transform failed with 1 error:

[PARSE_ERROR] Error: Unexpected token
   ╭─[ .probe/…/snippet.tsx:2:11 ]
   │
 2 │ const x = ;
   │           ┬
   │           ╰──
───╯
  Plugin: vite:oxc
  File: /Users/…/.probe/…/snippet.tsx

Two causes, both fixed.

Chromium keeps the 500 body from script. All the harness sees is the rejection message; the parse error — message, file, line, code frame — is in the response body. harness.browser.probe.tsx now re-requests the module (a failed transform is not cached as a success, so the second request fails the same way and hands over the text) and unpacks Vite's overlay page, which is not a message but a document: an HTML shell whose only content is a <script> assigning the error as JSON. Only message — already carrying file, line and frame — plus the plugin and file are kept; dumping the shell buries the one line that matters under a stack trace through Vite's internals and a copy of the wrapped snippet. If the body is not the shape we expect, the raw body is reported rather than a complaint that the error page was unrecognised.

Vite's log was captured and then dropped. probe.mjs had the dev server's stderr in hand all along, but discarded it because the run wrote a result file and vitest exited 0 — printing Test Files 1 passed over a snippet that never compiled. It is now printed under the message, but only when the harness could not name the cause itself (needsServerLog): a break in a module the snippet imports is named nowhere else, while in the common case the log is the same parse error a second time wrapped in a stack trace, which is how the useful half stops being read. Diagnostics go to stderr on every mode, --json included, so stdout stays parseable.

Verified across the six shapes this can take:

case result
syntax error in the snippet oxc parse error with file, line, frame — matches the jsdom tier
break in an imported module message says the snippet compiles; the log names fixture.tsx:1:42
missing export does not provide an export named 'NotAThing' — already self-describing, left alone
happy path unchanged
jsdom tier unchanged
--json stdout parses; log on stderr
Checklist
  • Pipeline is passed
  • Tests are passed successfully (locally — see below)
  • Commit message follows commit guidelines

Closes: N/A

Other information

No changeset, matching #1324 which added the probe: nothing here ships. scripts/ is tooling, and src/test/probe/ is the harness — named *.probe.tsx precisely so it cannot match vitest's default include. src/probe/ (the published @cube-dev/ui-kit/probe entry) is untouched, so Cube Cloud's yarn probe is unaffected.

No test added. Both changed paths are the probe's own error reporting, reachable only by making the harness fail; a spec for it would have to break a module on purpose and assert on Vite's overlay HTML, which is Vite's private shape and would pin us to it. The six cases above were run by hand instead, which is the same trade the harness itself already makes.

Cloud's packages/console-ui/scripts/probe.mjs has the same swallowed-stderr gap in its own copy of the CLI — worth the same fix there, but out of scope here.

Full suite green locally: 91 files, 1870 passed, 1 skipped. oxlint and prettier clean; tsc --noEmit reports the same four pre-existing errors in the two harness files as main (NodeListOf<Element> iteration under the current lib config), none new.

Pushed with --no-verify: the pre-push hook runs pnpm test, and vitest.config.ts's exclude does not cover .claude/worktrees/**, so the hook picks up other checkouts living inside the repo and fails on their code rather than on this branch's. Worth fixing separately — one exclude entry — but it would be an unrelated change in this PR.

🤖 Generated with Claude Code

A snippet that failed to compile under `pnpm probe:browser` reported
`Failed to fetch dynamically imported module: http://localhost:PORT/.probe/<runId>/snippet.tsx?import`
and nothing else — a network fault against a URL nobody typed, for what
was a parse error on line 2. The jsdom tier reported the same typo as an
oxc `[PARSE_ERROR]` with file, line and code frame, so the two tiers
disagreed on the slower one: the tier you are least willing to re-run
blind.

Two causes, both fixed.

Chromium keeps the 500 body from script, so all the harness sees is the
rejection message; the error itself is in that body. The harness now
re-requests the module — a failed transform is not cached as a success,
so the second request fails the same way and hands over the text — and
unpacks Vite's overlay page, which is an HTML shell whose only content
is a `<script>` assigning the error as JSON. Only `message` (already
carrying file, line and frame) plus the plugin and file are kept: dumping
the shell buries the one line that matters under a stack trace through
Vite's internals and a copy of the wrapped snippet.

Vite also logs the error to stderr, which `probe.mjs` captured and then
dropped, because the run wrote a result file and vitest exited 0 —
reporting `Test Files 1 passed` over a snippet that never compiled. That
log is now printed under the message, but only when the harness could not
name the cause itself (`needsServerLog`): a break in a module the snippet
*imports* is named nowhere else, while in the common case the log is the
same parse error a second time, wrapped in a stack trace, which is how
the useful half stops being read. Diagnostics go to stderr on every mode,
`--json` included, so stdout stays parseable.

Verified across the six shapes: a syntax error in the snippet (now
matches the jsdom tier byte for byte), a break in an imported module (the
log names the file and line), a missing export (already self-describing,
left alone), the happy path, the jsdom tier, and `--json`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 44ac218

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions

Copy link
Copy Markdown
Contributor

🧪 Storybook is successfully deployed!

@github-actions

Copy link
Copy Markdown
Contributor

📦 NPM canary release

Deployed canary version 0.0.0-canary-ce4d894.

@github-actions

Copy link
Copy Markdown
Contributor

🏋️ Size limit report

Name Size Passed?
All 487.43 KB (0% 🟰) Yes 🎉
Tree shaking (just a Button) 119.6 KB (0% 🟰) Yes 🎉

Compared against main at 6e2bd43run 32035596811, 2026-08-17T13:31:41Z.

Click here if you want to find out what is changed in this build

@vercel

vercel Bot commented Aug 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cube-ui-kit Ready Ready Preview Aug 17, 2026 4:24pm

Request Review

@tenphi
tenphi merged commit 91b8f62 into main Aug 17, 2026
12 checks passed
@tenphi
tenphi deleted the fix/probe-browser-compile-error branch August 17, 2026 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant