{"record":{"id":"092356f21fc2186b","repo":"oven-sh/bun","slug":"missing-output-for-id","errorCode":null,"errorMessage":"Missing output for ${id}","messagePattern":"Missing output for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/codegen/bundle-modules.ts","lineNumber":424,"sourceCode":"// Layout: [builtin functions combined source][\\0][module 0][\\n\\0][module 1][\\n\\0]...\n// WebCoreJSBuiltins.cpp's internalCombinedSource is the span at offset 0; the\n// internal modules follow at known offsets.\n//\n// In debug builds the module sources are read from disk (BUN_DYNAMIC_JS_LOAD_PATH),\n// so every module offset/length is 0. The functions span is still real in debug.\nconst moduleSpans: { enumName: string; offset: number; length: number }[] = [];\nlet blob: Buffer;\n{\n  const chunks: Buffer[] = [Buffer.from(functionsSource + \"\\0\", \"latin1\")];\n  let offset = chunks[0].length;\n  for (const id of layoutOrder(moduleList.slice(0, nativeStartIndex), outputs)) {\n    const enumName = idToEnumName(id);\n    if (debug) {\n      moduleSpans.push({ enumName, offset: 0, length: 0 });\n      continue;\n    }\n    const out = outputs.get(id.slice(0, -3).replaceAll(\"/\", path.sep));\n    if (!out) throw new Error(`Missing output for ${id}`);\n    checkAscii(out);\n    // Trailing \"\\n\\0\": the NUL keeps each entry a valid C string should anything\n    // downstream ever strlen into the blob.\n    const bytes = Buffer.from(out + \"\\n\\0\", \"latin1\");\n    chunks.push(bytes);\n    moduleSpans.push({ enumName, offset, length: bytes.length - 1 });\n    offset += bytes.length;\n  }\n  blob = Buffer.concat(chunks);\n}\n\nwriteIfNotChangedBinary(path.join(CODEGEN_DIR, \"InternalModuleRegistryConstants.bin\"), blob);\n\nwriteIfNotChanged(\n  path.join(CODEGEN_DIR, \"InternalModuleRegistryConstants.S\"),\n  `// Generated by src/codegen/bundle-modules.ts\n#if defined(__APPLE__)\n.section __TEXT,__const","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/codegen/bundle-modules.ts#L406-L442","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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)","If you added the module, verify it is inserted into moduleList at the correct position (JS modules must come before nativeStartIndex)","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","Diff bundle-modules.ts against main to find recent moduleList / nativeStartIndex edits"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// after the transpile loop, before blob assembly: every JS module id must have output\n// (add inside bundle-modules.ts right before the blob block)\nfor (const id of moduleList.slice(0, nativeStartIndex)) {\n  const key = id.slice(0, -3).replaceAll(\"/\", path.sep);\n  if (!outputs.has(key)) throw new Error(`Missing output for ${id}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When registering a new builtin module, add both the source file and the moduleList entry in the same commit, positioned before nativeStartIndex","Keep moduleList ids consistently '/'-separated with a .js suffix — the lookup key derives from that exact form","Run the codegen step locally on Windows too if you touch moduleList; separator bugs only show there"],"tags":["codegen","builtins","registry","build-invariant"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}