oven-sh/bun · error · Error

Missing output for ${id}

Error message

Missing output for ${id}

What it means

While assembling the InternalModuleRegistryConstants.bin module-source blob, codegen walks layoutOrder(moduleList) and looks up each module id in the outputs map populated by the transpile loop. This error means a module listed before nativeStartIndex produced no bundled output — the registry list and the actually-bundled set have diverged. It is a codegen consistency invariant, so the generated blob is never written with a hole in it.

Source

Thrown at src/codegen/bundle-modules.ts:424

// Layout: [builtin functions combined source][\0][module 0][\n\0][module 1][\n\0]...
// WebCoreJSBuiltins.cpp's internalCombinedSource is the span at offset 0; the
// internal modules follow at known offsets.
//
// In debug builds the module sources are read from disk (BUN_DYNAMIC_JS_LOAD_PATH),
// so every module offset/length is 0. The functions span is still real in debug.
const moduleSpans: { enumName: string; offset: number; length: number }[] = [];
let blob: Buffer;
{
  const chunks: Buffer[] = [Buffer.from(functionsSource + "\0", "latin1")];
  let offset = chunks[0].length;
  for (const id of layoutOrder(moduleList.slice(0, nativeStartIndex), outputs)) {
    const enumName = idToEnumName(id);
    if (debug) {
      moduleSpans.push({ enumName, offset: 0, length: 0 });
      continue;
    }
    const out = outputs.get(id.slice(0, -3).replaceAll("/", path.sep));
    if (!out) throw new Error(`Missing output for ${id}`);
    checkAscii(out);
    // Trailing "\n\0": the NUL keeps each entry a valid C string should anything
    // downstream ever strlen into the blob.
    const bytes = Buffer.from(out + "\n\0", "latin1");
    chunks.push(bytes);
    moduleSpans.push({ enumName, offset, length: bytes.length - 1 });
    offset += bytes.length;
  }
  blob = Buffer.concat(chunks);
}

writeIfNotChangedBinary(path.join(CODEGEN_DIR, "InternalModuleRegistryConstants.bin"), blob);

writeIfNotChanged(
  path.join(CODEGEN_DIR, "InternalModuleRegistryConstants.S"),
  `// Generated by src/codegen/bundle-modules.ts
#if defined(__APPLE__)
.section __TEXT,__const

View on GitHub (pinned to 8c5296ac45)

Solutions

  1. Check the failing id from the message: confirm its entrypoint file exists under src/js and that the transpile loop actually processed it (look for it in the temp modules_out dir)
  2. If you added the module, verify it is inserted into moduleList at the correct position (JS modules must come before nativeStartIndex)
  3. On Windows, compare separators: the outputs key uses path.sep — make sure the id in moduleList uses '/' and the .slice(0,-3) suffix stripping matches the '.js' extension
  4. Diff bundle-modules.ts against main to find recent moduleList / nativeStartIndex edits
Defensive patterns

Strategy: validation

Validate before calling

// after the transpile loop, before blob assembly: every JS module id must have output
// (add inside bundle-modules.ts right before the blob block)
for (const id of moduleList.slice(0, nativeStartIndex)) {
  const key = id.slice(0, -3).replaceAll("/", path.sep);
  if (!outputs.has(key)) throw new Error(`Missing output for ${id}`);
}

Prevention

When it happens

Trigger: Adding a new entry to moduleList in bundle-modules.ts whose entrypoint file does not exist or is not bundled; an id whose case or slash form does not match the outputs key (outputs keys use path.sep via replaceAll("/", path.sep), so separator/case mismatches on Windows miss); nativeStartIndex placed so a JS module is excluded from the transpile range but included in the blob range.

Common situations: Contributors registering a new builtin module (e.g. a new node: shim) and forgetting the source file or mis-ordering it relative to nativeStartIndex; Windows builds exposing separator normalization gaps between moduleList ids and outputs keys.

Related errors


AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16). Data as JSON: /api/errors/092356f21fc2186b. Report an issue: GitHub.