oven-sh/bun · error · Error
${typeName}.${name}: `this: true` accessors require `sharedT
Error message
${typeName}.${name}: `this: true` accessors require `sharedThis: true` What it means
generate-classes.ts supports `this: true` on proto accessors so a getter/setter receives the JS `this` value as an extra argument — but the generated thunk that forwards this_value only exists on the sharedThis code path (host_fn::host_fn_getter_this_shared). If a class definition opts out with `sharedThis: false` while a proto getter/setter uses `this: true`, the required thunk cannot be generated, so the generator rejects the combination. Note the generator default is sharedThis: true; this fires only on an explicit opt-out.
Source
Thrown at src/codegen/generate-classes.ts:2000
thunk(
classSymbolName(typeName, "call"),
`(global: &JSGlobalObject, callframe: &CallFrame) -> JSValue`,
` host_fn::host_fn_static(global, callframe, ${T}::call)`,
);
}
// ── proto getters / setters / fns ────────────────────────────────────────
// Closure form (`|t, g, c| T::method(t, g, c)`) rather than bare `T::method`
// so `&mut T → &T` autoref/coercion applies — many user impls take `&self`.
{
const seen = new Map<string, string>();
const exportNames = name => zigExportName(seen, n => protoSymbolName(typeName, n), proto[name]);
for (const name in proto) {
const { getter, setter, fn, this: thisValue = false, passThis, DOMJIT } = proto[name];
const names = exportNames(name);
if (thisValue && !sharedThis && (names.getter || names.setter)) {
throw new Error(`${typeName}.${name}: \`this: true\` accessors require \`sharedThis: true\``);
}
if (names.getter) {
const id = rustSnakeIdent(getter);
thunk(
names.getter,
`(this: ${recv}, ${thisValue ? "this_value: JSValue, " : ""}global: &JSGlobalObject) -> JSValue`,
thisValue
? ` host_fn::host_fn_getter_this_shared(this, this_value, global, |t, v, g| ${T}::${id}(t, v, g))`
: ` ${helper("host_fn_getter")}(this, global, |t, g| ${T}::${id}(t, g))`,
);
}
if (names.setter) {
const id = rustSnakeIdent(setter);
thunk(
names.setter,
`(this: ${recv}, ${thisValue ? "this_value: JSValue, " : ""}global: &JSGlobalObject, value: JSValue) -> bool`,View on GitHub (pinned to 8c5296ac45)
Solutions
- Remove the explicit `sharedThis: false` from the class definition so it uses the default shared this-handling the accessor requires
- Or drop `this: true` from the getter/setter if the accessor does not actually need the JS receiver
- Re-run codegen and confirm the generated host_fn_getter_this_shared thunk compiles
Example fix
// before (Foo.classes.ts)
export default {
sharedThis: false,
proto: { get owner() { /* this: true */ } },
} as ClassDefinition<Foo>;
// after
export default {
proto: { get owner() { /* this: true */ } },
} as ClassDefinition<Foo>; Defensive patterns
Strategy: validation
Validate before calling
// check the combo before codegen: this:true accessors need sharedThis
const sharedThis = obj.sharedThis !== false; // generator default is true
for (const [name, prop] of Object.entries(obj.proto ?? {})) {
const p = prop as { this?: boolean; getter?: unknown; setter?: unknown };
if (p.this === true && !sharedThis && (p.getter || p.setter)) {
throw new Error(`${obj.name}.${name}: this:true accessor requires sharedThis`);
}
} Prevention
- Avoid explicit `sharedThis: false` on new classes — it exists only as an opt-out for un-migrated types
- Any accessor that inspects the JS receiver needs `this: true`, which presupposes shared this-handling
When it happens
Trigger: Writing `const config = { sharedThis: false, proto: { get foo() { ... } } }` style definitions in a .classes.ts file — i.e. any proto getter/setter entry with `this: true` on a class whose definition explicitly sets `sharedThis: false`.
Common situations: Adding `this: true` to an accessor of an older class that predates the sharedThis default and carries an explicit `sharedThis: false`; migrating a mutable-self class to shared accessors without removing the opt-out.
Related errors
- "builtin" should be string
- ${typeName}: 'internal: true' on a property is not implement
- 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/7fc042b796381bef.
Report an issue: GitHub.