oven-sh/bun · error · Error
"builtin" should be string
Error message
"builtin" should be string
What it means
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++.
Source
Thrown at src/codegen/generate-classes.ts:224
setter = symbol + "SetterWrap";
}
if (fn) {
fn = symbol + "Callback";
}
} else {
if (getter) {
getter = symbolName(typeName, getter);
}
if (setter || writable) {
setter = symbolName(typeName, setter);
}
if (fn) {
fn = symbolName(typeName, fn);
}
}
if (builtin !== undefined) {
if (typeof builtin !== "string") throw new Error('"builtin" should be string');
return `
{ "${name}"_s, static_cast<unsigned>(JSC::PropertyAttribute::Builtin), NoIntrinsic, { HashTableValue::BuiltinGeneratorType, ${builtin}, ${
length || 0
} } }
`.trim();
} else if (fn !== undefined) {
if (DOMJIT) {
// { "getElementById"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction), NoIntrinsic, { HashTableValue::DOMJITFunctionType, jsTestDOMJITPrototypeFunction_getElementById, &DOMJITSignatureForTestDOMJITGetElementById } },
return `
{ "${name}"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function | JSC::PropertyAttribute::DOMJITFunction${extraPropertyAttributes}), NoIntrinsic, { HashTableValue::DOMJITFunctionType, ${fn}, &DOMJITSignatureFor${symbol} } }
`.trim();
}
return `
{ "${name}"_s, static_cast<unsigned>(JSC::PropertyAttribute::Function${extraPropertyAttributes}), NoIntrinsic, { HashTableValue::NativeFunctionType, ${fn}, ${
length || 0
} } }
`.trim();
} else if (getter && setter) {View on GitHub (pinned to 8c5296ac45)
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
Example fix
// before (Foo.classes.ts)
proto: {
toArray: { builtin: true },
}
// after
proto: {
toArray: { fn: "toArray", length: 0 },
} Defensive patterns
Strategy: validation
Validate before calling
// lint .classes.ts definitions: `builtin` must be a string
for (const [name, prop] of Object.entries({ ...obj.klass, ...obj.proto })) {
const p = prop as Record<string, unknown>;
if ("builtin" in p && typeof p.builtin !== "string") {
throw new Error(`${obj.name}.${name}: "builtin" should be string`);
}
} Type guard
// narrow a class-definition property before use
function isBuiltinProp(p: { builtin?: unknown }): p is { builtin: string } {
return "builtin" in p && typeof p.builtin === "string";
} Prevention
- 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
When it happens
Trigger: 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`).
Common situations: 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.
Related errors
- ${typeName}: 'internal: true' on a property is not implement
- ${typeName}.${name}: `this: true` accessors require `sharedT
- Expected filename for $${call_type} to have ${ext} extension
- Failed to generate classes
- Unknown $rust() file identifier ${JSON.stringify(filename)}.
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/f982d60c3ae05f63.
Report an issue: GitHub.