Skip to content

fix: clean up ESM registry when require() of ESM module fails#27288

Merged
Jarred-Sumner merged 2 commits intomainfrom
claude/fix-require-esm-registry-cleanup-27287
Feb 21, 2026
Merged

fix: clean up ESM registry when require() of ESM module fails#27288
Jarred-Sumner merged 2 commits intomainfrom
claude/fix-require-esm-registry-cleanup-27287

Conversation

@robobun
Copy link
Collaborator

@robobun robobun commented Feb 20, 2026

Summary

  • When require() loads an ESM module (.mjs) that throws during evaluation, the module was removed from requireMap but left in the ESM registry (Loader.registry) in a partially-initialized state
  • A subsequent import() of the same module would find this corrupt entry and throw ReferenceError: Cannot access 'foo' before initialization instead of re-throwing the original evaluation error
  • Fix by also deleting the module from Loader.registry in both overridableRequire and requireESMFromHijackedExtension when ESM evaluation fails, allowing import() to re-evaluate from scratch

Closes #27287

Test plan

  • Added regression test in test/regression/issue/27287.test.ts
  • Verified test fails with system bun (USE_SYSTEM_BUN=1)
  • Verified test passes with bun bd test
  • Manual verification: require() correctly throws original error, import() now re-throws the same error instead of ReferenceError

🤖 Generated with Claude Code

When `require()` loads an ESM module (.mjs) that throws during evaluation,
the module was removed from `requireMap` but left in the ESM registry
(`Loader.registry`) in a partially-initialized state. A subsequent
`import()` of the same module would find this corrupt entry and throw
`ReferenceError: Cannot access 'foo' before initialization` instead of
re-throwing the original evaluation error.

Fix by also deleting the module from `Loader.registry` in both
`overridableRequire` and `requireESMFromHijackedExtension` when ESM
evaluation fails, allowing `import()` to re-evaluate from scratch.

Closes #27287

Co-Authored-By: Claude <noreply@anthropic.com>
@robobun
Copy link
Collaborator Author

robobun commented Feb 20, 2026

Updated 10:43 AM PT - Feb 20th, 2026

@alii, your commit c17ded7 has 5 failures in Build #37738 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 27288

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

bun-27288 --bun

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 20, 2026

No actionable comments were generated in the recent review. 🎉


Walkthrough

The changes fix a bug where requiring a failing ESM module via CommonJS would leave it in a partially-initialized state in the ESM registry. The fix ensures failed modules are fully cleared from both the require map and ESM registry on error, allowing subsequent imports to re-evaluate the module from scratch.

Changes

Cohort / File(s) Summary
ESM/CJS Error Handling Fix
src/js/builtins/CommonJS.ts
Added cleanup of the ESM registry (Loader.registry.$delete(id)) alongside the existing $requireMap deletion when errors occur during require() calls in both the overridableRequire and requireESMFromHijackedExtension code paths.
Regression Test for Issue #27287
test/regression/issue/27287.test.ts
Added comprehensive regression test verifying that requiring a failing ESM module via CJS does not corrupt state for subsequent dynamic imports. Tests error propagation, exit codes, and absence of ReferenceErrors in output.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: fixing ESM registry cleanup when require() of an ESM module fails.
Description check ✅ Passed The description covers both required sections: 'What does this PR do?' (detailed summary of the problem and fix) and 'How did you verify your code works?' (test plan with verification steps).
Linked Issues check ✅ Passed The PR implementation directly addresses issue #27287 by fixing the core problem: deleting modules from Loader.registry when ESM evaluation fails, allowing subsequent imports to re-evaluate from scratch instead of hitting uninitialized state.
Out of Scope Changes check ✅ Passed All changes are in scope: modifications to CommonJS.ts fix the registry cleanup issue, and the regression test in 27287.test.ts directly validates the fix for the linked issue.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@claude
Copy link
Contributor

claude bot commented Feb 20, 2026

Newest first

c17de — Looks good!

Reviewed 2 files across src/js/builtins/ and test/regression/issue/: Fixes a bug where CJS require() of a failing ESM module left a corrupted entry in the ESM registry, causing subsequent import() calls to fail with a ReferenceError; the fix ensures cleanup of both the require map and ESM registry on failure.

Previous reviews

68641 — Looks good!

Reviewed 2 files across src/js/builtins/ and test/regression/issue/: Adds cleanup of the ESM registry when require() of an ESM module fails, ensuring subsequent import() calls can re-evaluate the module properly.

@Jarred-Sumner Jarred-Sumner merged commit 21c3439 into main Feb 21, 2026
48 of 63 checks passed
@Jarred-Sumner Jarred-Sumner deleted the claude/fix-require-esm-registry-cleanup-27287 branch February 21, 2026 01:08
Jarred-Sumner pushed a commit that referenced this pull request Feb 21, 2026
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.

CJS require() of failing ESM produces uninitialized exports on import()

3 participants