oven-sh/bun · error · Error
${typeName}: 'internal: true' on a property is not implement
Error message
${typeName}: 'internal: true' on a property is not implemented (no users today; the visitChildren plumbing for it was never wired up consistently). Use 'cache: true' or add it to 'values' instead. What it means
A deliberate guard in generate-classes.ts: properties in *.classes.ts files cannot use `internal: true`. Although the option appears in the schema, the GC visitChildren plumbing it implies was never wired up consistently, so the generator hard-rejects it instead of emitting broken tracing code. The message points at the two supported alternatives: `cache: true` (getter whose result is cached and traced) or adding the slot to the class `values` array.
Source
Thrown at src/codegen/generate-classes.ts:1064
values.push([name, cacheName]);
}
}
return values;
}
function generateClassHeader(typeName, obj: ClassDefinition) {
var { klass, proto, JSType = "ObjectType", values = [] } = obj;
const name = className(typeName);
if (obj.estimatedSize) {
externs += `extern JSC_CALLCONV size_t ${symbolName(typeName, "estimatedSize")}(void* ptr);` + "\n";
}
for (const a of [...Object.values(klass), ...Object.values(proto)]) {
if (a.internal === true) {
throw new Error(
`${typeName}: 'internal: true' on a property is not implemented (no users today; the visitChildren plumbing for it was never wired up consistently). Use 'cache: true' or add it to 'values' instead.`,
);
}
}
const DECLARE_VISIT_CHILDREN =
values.length ||
obj.estimatedSize ||
obj.valuesArray ||
[...Object.values(klass), ...Object.values(proto)].find(a => a.cache === true)
? "DECLARE_VISIT_CHILDREN;\n"
: "";
var weakOwner = "";
var weakInit = ``;
if (obj.hasPendingActivity) {
weakInit = `m_weakThis = JSC::Weak<${name}>(this, getOwner());`;
weakOwner = `
JSC::Weak<${name}> m_weakThis;View on GitHub (pinned to 8c5296ac45)
Solutions
- Replace `internal: true` with `cache: true` if the property is a JS-visible getter whose value should be retained and GC-traced
- Or declare the field in the class's `values` array so it participates in visitChildren through the normal values plumbing
- If neither fits, the property likely should not be in the definition at all — implement it as a manual C++/Rust method
Example fix
// before (Foo.classes.ts)
proto: {
socket: { internal: true },
}
// after
proto: {
socket: { cache: true },
} Defensive patterns
Strategy: validation
Validate before calling
// reject `internal: true` before running codegen
for (const [name, prop] of Object.entries({ ...obj.klass, ...obj.proto })) {
if ((prop as any)?.internal === true) {
throw new Error(`${obj.name}.${name}: internal: true is not implemented — use cache: true or values`);
}
} Prevention
- Model retained per-instance JS-visible state with cache: true or the values array; `internal` is dead schema
- If you need untraced native state, keep it as plain Rust/C++ fields, not a class-definition property
When it happens
Trigger: Declaring any klass or proto property with `internal: true` in a .classes.ts file, e.g. `proto: { underlying: { internal: true } }`, then running the class codegen step.
Common situations: Contributors trying to expose an internal accessor for C++/Rust-side state without making it a full cached property; copying old definitions from before the guard existed.
Related errors
- "builtin" should be string
- ${typeName}.${name}: `this: true` accessors require `sharedT
- Failed to generate classes
- Expected filename for $${call_type} to have ${ext} extension
- Unknown $rust() file identifier ${JSON.stringify(filename)}.
AI-assisted analysis of oven-sh/bun@8c5296ac45 (2026-08-16).
Data as JSON: /api/errors/d730941d2556090c.
Report an issue: GitHub.