oven-sh/bun · critical · Error
Could not find BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE in Nati
Error message
Could not find BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE in NativeModuleList.h. Knowing native module IDs is a part of the codegen process.
What it means
internal-module-registry-scanner.ts reads src/jsc/modules/NativeModuleList.h and parses every `macro("id", Enum)` entry inside BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE to assign native module IDs used throughout codegen. If zero entries matched (nextNativeModuleId === 0), the header was moved, renamed, or reformatted, and codegen cannot proceed without those IDs.
Source
Thrown at src/codegen/internal-module-registry-scanner.ts:56
const nativeModuleH = fs.readFileSync(path.join(basedir, "../jsc/modules/NativeModuleList.h"), "utf8");
for (const [_, idString, enumValue] of nativeModuleH.matchAll(/macro\((.*?),(.*?)\)/g)) {
const processedIdString = JSON.parse(idString.trim().replace(/_s$/, ""));
const processedEnumValue = enumValue.trim();
const processedNumericId = nextNativeModuleId++;
nativeModuleIds[processedIdString] = processedNumericId;
nativeModuleEnums[processedIdString] = processedEnumValue;
nativeModuleEnumToId[processedEnumValue] = processedNumericId;
}
const nativeStartIndex = moduleList.length;
for (const [id] of Object.entries(nativeModuleIds)) {
moduleList.push(id);
internalRegistry.set(id, moduleList.length - 1);
}
if (nextNativeModuleId === 0) {
throw new Error(
"Could not find BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE in NativeModuleList.h. Knowing native module IDs is a part of the codegen process.",
);
}
function codegenRequireId(id: string) {
return `(__intrinsic__getInternalField(__intrinsic__internalModuleRegistry, ${id}) || __intrinsic__createInternalModuleById(${id}))`;
}
const requireTransformer = (specifier: string, from: string) => {
const directMatch = internalRegistry.get(specifier);
if (directMatch) return codegenRequireId(`${directMatch}/*${specifier}*/`);
const relativeMatch =
resolveSyncOrNull(specifier, path.join(basedir, path.dirname(from))) ?? resolveSyncOrNull(specifier, basedir);
const suffix =
'Only files in "src/js" besides "src/js/builtins" can be imported here. Note that the "node:" or "bun:" prefix is required here.';
View on GitHub (pinned to 8c5296ac45)
Solutions
- Restore src/jsc/modules/NativeModuleList.h at that exact path with the `#define BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE(macro)` block.
- Keep entries in the `macro("fs", Fs)` shape — string literal ID first, enum identifier second — so the scanner regex matches.
- If the header must move, update the path in internal-module-registry-scanner.ts (line 38) in the same commit.
Defensive patterns
Strategy: validation
Validate before calling
const headerPath = path.join(basedir, "../jsc/modules/NativeModuleList.h");
const header = fs.readFileSync(headerPath, "utf8");
if (!/macro\((.*?),(.*?)\)/.test(header)) {
throw new Error(`${headerPath}: no macro(id, Enum) entries found — header was moved or reformatted`);
} Prevention
- Treat NativeModuleList.h's macro name and file location as a codegen contract: change scanner and header together.
- Add a CI check that codegen output is unchanged after reformatting PRs (catches marker-destroying rustfmt/clang-format changes).
- Do not reformat or rename inside the BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE block.
When it happens
Trigger: The file src/jsc/modules/NativeModuleList.h is missing, the macro BUN_FOREACH_ESM_AND_CJS_NATIVE_MODULE was renamed, or the entries no longer match the /macro\((.*?),(.*?)\)/ pattern (e.g. changed to macro(id, Enum) without string quotes or a different helper name).
Common situations: Reformatting or restructuring the JSC module list header; moving it into another directory during a refactor; a bad merge that dropped the #define block.
Related errors
- file did not exist after write: ${outputPath}
- Builtin Bundler: do not use import.meta.require() (in ${file
- Errors in ${entrypoint}: ${errors.map(x => x[1]).join("\n")}
- Missing output for ${id}
- "builtin" should be string
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/6201e9b7be991f50.
Report an issue: GitHub.