karatelabs/karate · error · TypeError
Method WeakMap.prototype called on incompatible receiver
Error message
Method WeakMap.prototype called on incompatible receiver
What it means
WeakMap prototype methods (get, set, has, delete) must be invoked with a real JsWeakMap as `this`. Karate's asWeakMap() inspects context.getThisObject() and throws this TypeError when the receiver is not a JsWeakMap — for example when a method is detached and called standalone, or called on a subclass/proxy instance that isn't the engine's WeakMap class.
Solutions
- Bind methods before detaching: const g = wm.get.bind(wm).
- Always call methods on the instance: wm.get(key), not WeakMap.prototype.get.call(other, key).
- Ensure helper functions receive the actual WeakMap instance created in the same engine.
- If you need generic behavior, accept the map as a parameter and call methods on it directly.
Example fix
// before const get = wm.get; get(key); // incompatible receiver // after const get = wm.get.bind(wm); get(key);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(m instanceof WeakMap)) throw new Error('receiver must be a WeakMap'); Type guard
function isWeakMap(x) { try { WeakMap.prototype.set.call(x, {}, 1); return true; } catch (e) { return false; } } Try / catch
try { return wm.get(key); } catch (e) { if (String(e).indexOf('incompatible receiver') !== -1) throw new Error('use wm.get.bind(wm) before detaching methods'); throw e; } Prevention
- Bind methods before extracting them from instances
- Call prototype methods only with genuine WeakMap receivers
- Create and use WeakMaps within the same script/engine context
When it happens
Trigger: const g = wm.get; g(key) (unbound method); WeakMap.prototype.has.call(nonWeakMap, key); calling methods on an object that merely looks like a WeakMap; calling a prototype method via call/apply with the wrong this.
Common situations: Extracting methods for callbacks (forEach-style usage) without binding; mixing WeakMaps across script contexts/engines where classes differ; passing map-like mocks into helper functions.
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
- Invalid value used as weak map key
- Constructor WeakMap requires 'new'
- WeakMap.prototype.set is not callable
- Iterator value is not an entry object
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/7a54c6587d807451.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsWeakMapPrototype.java:51
static final JsWeakMapPrototype INSTANCE = new JsWeakMapPrototype();
private JsWeakMapPrototype() {
super(JsObjectPrototype.INSTANCE);
install("get", 1, this::get);
install("set", 2, this::set);
install("has", 1, this::has);
install("delete", 1, this::delete);
// Spec tags WeakMap via @@toStringTag rather than a builtin class check.
install("@@toStringTag", "WeakMap");
installConstructor("WeakMap");
}
private static JsWeakMap asWeakMap(Context context) {
Object thisObj = context.getThisObject();
if (thisObj instanceof JsWeakMap m) {
return m;
}
throw JsErrorException.typeError("Method WeakMap.prototype called on incompatible receiver");
}
private Object get(Context context, Object[] args) {
return asWeakMap(context).getValue(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
private Object set(Context context, Object[] args) {
JsWeakMap m = asWeakMap(context);
m.setValue(args.length > 0 ? args[0] : Terms.UNDEFINED, args.length > 1 ? args[1] : Terms.UNDEFINED);
return m;
}
private Object has(Context context, Object[] args) {
return asWeakMap(context).hasKey(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
private Object delete(Context context, Object[] args) {
return asWeakMap(context).deleteKey(args.length > 0 ? args[0] : Terms.UNDEFINED);View on GitHub (pinned to a22eb90246)