Skip to content

esm: report the importing file when a named import cannot be resolved - #36635

Draft
robobun wants to merge 2 commits into
mainfrom
farm/0eec2e41/import-error-location
Draft

esm: report the importing file when a named import cannot be resolved#36635
robobun wants to merge 2 commits into
mainfrom
farm/0eec2e41/import-error-location

Conversation

@robobun

@robobun robobun commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator

Fixes #5582. Fixes #20667.

Reproduction

# dep.ts
export const b = 1;
# index.ts
import { a } from "./dep.ts";
$ bun index.ts
SyntaxError: Export named 'a' not found in module '/repro/dep.ts'.

The error names dep.ts but not index.ts, so in a project where many files import from dep.ts there is no way to locate the failing import statement. Node prints file:///repro/index.ts:1 with the offending line.

Cause

The error is thrown in CyclicModuleRecord::initializeEnvironment during module linking, from a C++ microtask with no JS on the stack. The SyntaxError carries only the message text and is handed to Bun's printer with an empty stack trace, so fromErrorInstance's sourceURL/line/column fallback finds nothing.

Fix

JavaScriptCore change in oven-sh/WebKit#378: ImportEntry records the specifier's source offset (one unsigned), and the throw site attaches sourceURL / line / column (both as ErrorInstance::m_sourceURL/m_lineColumn and as DontEnum own properties) for the importing module. Bun's existing ZigException.cpp::fromErrorInstance already reads those properties and remap_zig_exception already remaps them through the sourcemap, so no bun-side code change is needed.

With the bump:

$ bun index.ts
1 | import { a } from "./dep.ts";
    ^
SyntaxError: Export named 'a' not found in module '/repro/dep.ts'.
      at /repro/index.ts:1:1

The indirect-export (export { x } from "./dep") and ambiguous-binding cases route through the same helper and at least carry the importing module's sourceURL.

Verification

test/js/bun/resolve/esm-link-error-location.test.ts covers the direct case, an indirect chain (entry → middle → dep) that must name middle.mjs and not the entry point, and a caught dynamic import() rejection whose .sourceURL/.line point at the importing file. All three fail on released bun and pass with the bump.

test/js/bun/typescript/type-export.test.ts (import not found) and test/js/bun/resolve/resolve-error.test.ts are unchanged and green.

WebKit bump

WEBKIT_VERSION currently points at the preview build of oven-sh/WebKit#378 so CI can exercise the change. It will be updated to the merged main sha before this is undrafted. The preview built green on every WebKit CI lane (linux glibc/musl/android, macOS, windows x64/arm64, freebsd).

The gate's fail-before check cannot mechanically prove this because the fix is in the bumped prebuilt, not in src/; stashing src/ leaves the bump in place. The fail-before evidence is USE_SYSTEM_BUN=1 bun test test/js/bun/resolve/esm-link-error-location.test.ts → 3 fail.


[decide:webkit] gate passed · iteration 1 · 2 files touched

passes on PR (with fix)
Test-only change.

Debug/ASAN (expected pass):
$ bun bd test 'test/js/bun/resolve/esm-link-error-location.test.ts'
$ BUN_DEBUG_QUIET_LOGS=1 bun scripts/build.ts --profile=debug --quiet test test/js/bun/resolve/esm-link-error-location.test.ts
bun test v1.4.0 (d5059e897)

test/js/bun/resolve/esm-link-error-location.test.ts:
(pass) ESM link-time SyntaxError reports the importing file > entry point imports a missing named export [629.96ms]
(pass) ESM link-time SyntaxError reports the importing file > indirect: the failing import is not in the entry point [1187.18ms]
(pass) ESM link-time SyntaxError reports the importing file > dynamic import() rejection carries importer location on the error [823.39ms]

 3 pass
 0 fail
 12 expect() calls
Ran 3 tests across 1 file. [9.59s]
Exit: 0
diff hotspot
scripts/build/deps/webkit.ts                       |  2 +-
 .../js/bun/resolve/esm-link-error-location.test.ts | 71 ++++++++++++++++++++++
 2 files changed, 72 insertions(+), 1 deletion(-)

gate history · 2 passed · 0 rejected · iteration 1

evidence per changed file
file                                                 reads  edits  tests
scripts/build/deps/webkit.ts                             1      1      0
test/js/bun/resolve/esm-link-error-location.test.ts      1      3      0

Fixes #5582. The SyntaxError thrown during module linking when a named
import has no matching export only named the imported-from module; in a
multi-file project there was no way to find which file contained the
failing import statement.

The fix lives in JavaScriptCore (oven-sh/WebKit#378): ImportEntry now
records the specifier's source offset and initializeEnvironment attaches
sourceURL / line / column to the SyntaxError. Bun's existing error
printer reads those properties and renders the location (with sourcemap
remapping and the source-line preview), so the bun-side change is just
the WEBKIT_VERSION bump and the regression test.

WEBKIT_VERSION points at the PR preview build for now; it will be
updated to the merged main sha once oven-sh/WebKit#378 lands.
@robobun

robobun commented Aug 1, 2026

Copy link
Copy Markdown
Collaborator Author
Updated 3:14 AM PT - Aug 1st, 2026

@robobun, your commit d5059e8 has 1 failures in Build #86709 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 36635

That installs a local version of the PR into your bun-36635 executable, so you can run:

bun-36635 --bun

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Found 1 issue this PR may fix:

  1. Missing import location on import error #20667 - Reports the same problem: ESM "Export named not found" errors don't show the importing file's location, making it hard to find the offending import statement

If this is helpful, copy the block below into the PR description to auto-close this issue on merge.

Fixes #20667

🤖 Generated with Claude Code

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing import location on import error Show stacktrace when import is invalid

2 participants