{"record":{"id":"34ad2dca8f2821f3","repo":"oven-sh/bun","slug":"nodeerror-can-t-fit-count-codes-in-a-u16","errorCode":null,"errorMessage":"NodeError can't fit ${count} codes in a u16","messagePattern":"NodeError can't fit (.+?) codes in a u16","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/codegen/generate-node-errors.ts","lineNumber":17,"sourceCode":"import path from \"node:path\";\nimport NodeErrors from \"../jsc/bindings/ErrorCode.ts\";\nimport { writeIfNotChanged } from \"./helpers.ts\";\nconst outputDir = process.argv[2];\n\nif (!outputDir) {\n  throw new Error(\"Missing output directory\");\n}\n\nconst extra_count = NodeErrors.map(x => x.slice(3))\n  .filter(x => x.length > 0)\n  .reduce((ac, cv) => ac + cv.length, 0);\nconst count = NodeErrors.length + extra_count;\n\nif (count > 1 << 16) {\n  // increase size of the enums below to have more tags\n  throw new Error(`NodeError can't fit ${count} codes in a u16`);\n}\n\nlet enumHeader = ``;\nlet listHeader = ``;\nlet rustConsts = ``;\nlet rustAliases = ``;\nlet rustCodeStr = ``;\n\nenumHeader = `\n// clang-format off\n// Generated by: src/codegen/generate-node-errors.ts\n// Input:        src/jsc/bindings/ErrorCode.ts\n#pragma once\n\n#include <cstdint>\n\nnamespace Bun {\n  static constexpr size_t NODE_ERROR_COUNT = ${count};","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/codegen/generate-node-errors.ts#L1-L35","documentation":"generate-node-errors.ts counts every entry in the NodeErrors table plus all their sub-codes (the nested arrays from src/jsc/bindings/ErrorCode.ts) and checks the total fits in a u16, because the generated error-tag enum and its wire representation are 16-bit. If the table grows past 65,536 codes, codegen aborts rather than silently truncating tags. The comment at the throw site states the remedy: widen the generated enums.","triggerScenarios":"Adding a large batch of Node error codes/sub-codes to src/jsc/bindings/ErrorCode.ts (or a script generating them) so the total exceeds 1 << 16; extremely unlikely from hand edits alone.","commonSituations":"Bulk-importing error codes from a new Node version or generating per-syscall/per-path error variants programmatically; essentially a theoretical guard for maintainers of the error table.","solutions":["Confirm the count is legitimate (print NodeErrors.length + extra_count) and not an accident, e.g. an accidentally nested array multiplying sub-codes","If genuine: widen the tag enum and every u16 field/argument that carries the tag in the generated headers and consumers (the throw-site comment instructs exactly this)","Audit consumers of the generated tags (error construction, serialization) so the widened type propagates consistently"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before regenerating, confirm the table still fits u16\nimport NodeErrors from \"../jsc/bindings/ErrorCode.ts\";\nconst extra = NodeErrors.map(x => x.slice(3)).filter(x => x.length > 0).reduce((a, c) => a + c.length, 0);\nif (NodeErrors.length + extra > (1 << 16)) {\n  throw new Error(\"error table exceeds u16 — widen the generated enums first\");\n}","typeGuard":"function errorCountFitsU16(entries: unknown[][]): boolean {\n  const total = entries.reduce((a, e) => a + 1 + Math.max(0, e.length - 3), 0);\n  return total <= (1 << 16);\n}","tryCatchPattern":null,"preventionTips":["Bulk-import error codes with a script that checks the u16 budget before committing ErrorCode.ts","Watch for accidentally nested arrays in the table — they multiply sub-code counts silently"],"tags":["codegen","node-compat","error-codes","capacity-limit"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}