Skip to content

browser run: compile errors report no line, column, or source #353

Closed

Description

@ankitranjan7

Summary

A program that fails to compile inside browser run is reported without any line, column, or source context, and is prefixed with a message that points at async plumbing rather than at the program. A one-character quoting mistake becomes an unactionable failure.

Repro

webcmd --session <id> browser run --stdin --no-snapshot-diff <<'JS'
const a = 1;
const s = 'x'y';
return a;
JS

Actual:

✖  BROWSER_RUN_SYNTAX_ERROR: QuickJS promise rejected: expecting ';'
✖  Fix the browser-run JavaScript syntax and retry.

No position. On a real program this is unactionable — the case that surfaced this had a 2,361-character line and reported only invalid number literal.

Cause

src/browser/run/runner.ts compiles the program with new AsyncFunction(source) inside the Promise.race:

value = await Promise.race([new AsyncFunction(source)(), cancellation]);

Two consequences:

  1. A compile failure surfaces as a rejected promise, so quickjs-host.ts prefixes it with QuickJS promise rejected:. Readers chase heredocs, await, and shell quoting instead of the program.
  2. The position is discarded. QuickJS does supply it — probing the sandbox directly returns lineNumber, columnNumber, and a stack of at <input>:4:14 — but normalizeExecutionError uses only .message.

The hint (Fix the browser-run JavaScript syntax and retry) restates the error code and names no cause.

Impact

Measured in the internal task eval: agents given this error blamed shell interpolation, encoded data URLs, arrow syntax, and top-level await in turn. Two scenarios abandoned the supplied page entirely and rebuilt a substitute rather than fix a single quote. The underlying mistake in every case was the same — an unescaped ' inside a single-quoted string holding a URL or HTML.

Expected

✖  BROWSER_RUN_SYNTAX_ERROR: invalid number literal at line 1, column 1215
  tput%3E%3Cscript%3Econst%20form%3Ddocument.querySelector('%23registration')%2Cdr
                                                             ^
✖  Your program failed to compile; the browser was never touched. A common cause
   is an unescaped quote when embedding a URL or HTML in a string literal — use
   double quotes or a template literal for values that contain apostrophes.

Fix

Compile before racing, and turn a compile failure into a BROWSER_RUN_SYNTAX_ERROR carrying:

  • the caller's own line and column — new AsyncFunction(body) prepends two lines of wrapper, so subtract them
  • a windowed excerpt with a caret, so a 2,000-character line stays readable
  • a hint naming the quoting cause

Also skip the host stage prefix in quickjs-host.ts#toError for errors that already carry a BROWSER_RUN_ code.

Note

src/browser/run/runner.test.ts imports MemorySnapshotBaselineStore twice, so the file fails to load and its 74 tests have never run. They pass once the duplicate is removed.

Activity

  1. ankitranjan7 commented on Aug 19, 2026

    @ankitranjan7
    ContributorAuthor

    Fixed locally on fix/browser-run-syntax-position (commit 93702f9), not yet pushed. Related: #354, #355 — both surface through the same error path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions