karatelabs/karate · error · TypeError
Method WeakSet.prototype called on incompatible receiver
Error message
Method WeakSet.prototype called on incompatible receiver
What it means
WeakSet prototype methods (add, has, delete) require `this` to be an actual JsWeakSet. Karate's asWeakSet() checks context.getThisObject() and throws this TypeError for any incompatible receiver — detached methods called with a wrong this, or non-WeakSet objects.
Solutions
- Bind before detaching: const add = ws.add.bind(ws).
- Call methods directly on the instance: ws.add(obj).
- Pass the WeakSet instance itself as a callback: arr.forEach(fn, ws) won't help for add — use arr.forEach(v => ws.add(v)).
- Verify the receiver was created via new WeakSet() in the same evaluation context.
Example fix
// before const add = ws.add; [obj1, obj2].forEach(add); // incompatible receiver (this=undefined) // after [obj1, obj2].forEach(o => ws.add(o));
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(s instanceof WeakSet)) throw new Error('receiver must be a WeakSet'); Type guard
function isWeakSet(x) { try { WeakSet.prototype.has.call(x, {}); return true; } catch (e) { return false; } } Try / catch
try { ws.add(v); } catch (e) { if (String(e).indexOf('incompatible receiver') !== -1) throw new Error('bind ws.add before using it as a callback'); throw e; } Prevention
- Wrap detached methods: ws.add.bind(ws)
- Use arrow callbacks (v => ws.add(v)) instead of passing the method itself
- Only call prototype methods with real WeakSet receivers
When it happens
Trigger: const a = ws.add; a(obj) (unbound); WeakSet.prototype.has.call(fakeSet, obj); invoking prototype methods on plain objects or objects from a different engine context.
Common situations: Passing ws.add as a callback (e.g. to forEach) without binding; helper utilities expecting duck-typed sets; cross-context object mixing in embedded engines.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- RegExp.prototype. called on incompatible receiver
- Method WeakMap.prototype called on incompatible receiver
- Invalid value used in weak set
- Constructor WeakSet requires 'new'
- WeakSet.prototype.add is not callable
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/318d8678cc4895ab.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsWeakSetPrototype.java:49
class JsWeakSetPrototype extends Prototype {
static final JsWeakSetPrototype INSTANCE = new JsWeakSetPrototype();
private JsWeakSetPrototype() {
super(JsObjectPrototype.INSTANCE);
install("add", 1, this::add);
install("has", 1, this::has);
install("delete", 1, this::delete);
install("@@toStringTag", "WeakSet");
installConstructor("WeakSet");
}
private static JsWeakSet asWeakSet(Context context) {
Object thisObj = context.getThisObject();
if (thisObj instanceof JsWeakSet s) {
return s;
}
throw JsErrorException.typeError("Method WeakSet.prototype called on incompatible receiver");
}
private Object add(Context context, Object[] args) {
JsWeakSet s = asWeakSet(context);
s.addValue(args.length > 0 ? args[0] : Terms.UNDEFINED);
return s;
}
private Object has(Context context, Object[] args) {
return asWeakSet(context).has(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
private Object delete(Context context, Object[] args) {
return asWeakSet(context).deleteValue(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
}
View on GitHub (pinned to a22eb90246)