{"record":{"id":"f982d60c3ae05f63","repo":"oven-sh/bun","slug":"builtin-should-be-string","errorCode":null,"errorMessage":"\"builtin\" should be string","messagePattern":"\"builtin\" should be string","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/codegen/generate-classes.ts","lineNumber":224,"sourceCode":"      setter = symbol + \"SetterWrap\";\n    }\n    if (fn) {\n      fn = symbol + \"Callback\";\n    }\n  } else {\n    if (getter) {\n      getter = symbolName(typeName, getter);\n    }\n    if (setter || writable) {\n      setter = symbolName(typeName, setter);\n    }\n    if (fn) {\n      fn = symbolName(typeName, fn);\n    }\n  }\n\n  if (builtin !== undefined) {\n    if (typeof builtin !== \"string\") throw new Error('\"builtin\" should be string');\n    return `\n{ \"${name}\"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, ${builtin}, ${\n      length || 0\n    } } }\n`.trim();\n  } else if (fn !== undefined) {\n    if (DOMJIT) {\n      // { \"getElementById\"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { HashTableValue::DOMJITFunctionType, jsTestDOMJITPrototypeFunction_getElementById, &DOMJITSignatureForTestDOMJITGetElementById } },\n      return `\n      { \"${name}\"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction${extraPropertyAttributes}), NoIntrinsic, { HashTableValue::DOMJITFunctionType, ${fn}, &DOMJITSignatureFor${symbol} } }\n      `.trim();\n    }\n    return `\n{ \"${name}\"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function${extraPropertyAttributes}), NoIntrinsic, { HashTableValue::NativeFunctionType, ${fn}, ${\n      length || 0\n    } } }\n`.trim();\n  } else if (getter && setter) {","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/src/codegen/generate-classes.ts#L206-L242","documentation":"In Bun's class-bindings generator (src/codegen/generate-classes.ts), a property in a *.classes.ts definition that sets the `builtin` key must give a string naming a JSC builtin generator function — the value is emitted verbatim into a HashTableValue BuiltinGeneratorType row. This error fires when `builtin` is present but has any other type (boolean, number, object), which would generate invalid C++.","triggerScenarios":"Writing a class definition like `proto: { foo: { builtin: true } }` or `builtin: 1` in a file under src/ ending in .classes.ts, then running codegen (`bun run build`).","commonSituations":"Contributors assuming `builtin: true` is a boolean feature flag; copy-paste typos from neighboring fn/getter entries; refactors that move a string constant into a variable of the wrong type.","solutions":["Open the .classes.ts file for the class named in your build log and find the property with a non-string `builtin` value","Either set it to a string naming the intended JSC builtin generator, or delete `builtin` and declare the member properly with `fn`/`getter`","Re-run codegen to confirm the generated HashTable values compile"],"exampleFix":"// before (Foo.classes.ts)\nproto: {\n  toArray: { builtin: true },\n}\n\n// after\nproto: {\n  toArray: { fn: \"toArray\", length: 0 },\n}","handlingStrategy":"validation","validationCode":"// lint .classes.ts definitions: `builtin` must be a string\nfor (const [name, prop] of Object.entries({ ...obj.klass, ...obj.proto })) {\n  const p = prop as Record<string, unknown>;\n  if (\"builtin\" in p && typeof p.builtin !== \"string\") {\n    throw new Error(`${obj.name}.${name}: \"builtin\" should be string`);\n  }\n}","typeGuard":"// narrow a class-definition property before use\nfunction isBuiltinProp(p: { builtin?: unknown }): p is { builtin: string } {\n  return \"builtin\" in p && typeof p.builtin === \"string\";\n}","tryCatchPattern":null,"preventionTips":["Remember `builtin` names a JSC builtin generator string, it is not a boolean flag","Most members want fn/getter/setter; reach for builtin only when mirroring an upstream WebKit/JSC builtin"],"tags":["codegen","classes","bindings","configuration"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}