karatelabs/karate · error · JsErrorException
Method Map.prototype called on incompatible receiver
Error message
Method Map.prototype called on incompatible receiver
What it means
Map.prototype methods (get, set, has, delete, clear, etc.) must be invoked on an actual Map instance as `this`. Karate's `asMap` checks `context.getThisObject() instanceof JsMap` and throws this TypeError otherwise, mirroring the ES spec's MakeOrdinaryObjectCheck on the receiver.
Solutions
- Bind the method: `const get = map.get.bind(map)`
- Use arrow wrappers: `arr.map(k => map.get(k))`
- Ensure .call/.apply receivers are real `new Map()` instances
- Recreate the Map if the value was accidentally replaced by a plain object
Example fix
// before
const get = map.get;
const v = get('key'); // TypeError
// after
const get = map.get.bind(map);
const v = get('key'); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(m instanceof Map)) { throw new Error('receiver must be a real Map instance'); } Type guard
function isMap(x) { return x instanceof Map; } Try / catch
try {
return mapLike.get('key');
} catch (e) {
if (String(e.message).includes('incompatible receiver')) {
throw new Error('called a Map.prototype method without a Map as this — bind the method');
} else throw e;
} Prevention
- Never destructure Map methods without .bind(map)
- Use arrow-function wrappers for callbacks: (k) => map.get(k)
- Check .call/.apply receivers are Map instances
When it happens
Trigger: Calling the method detached from the instance: `const g = map.get; g('key')`; destructuring methods off a Map; `Map.prototype.get.call(nonMapObject, 'k')`; calling a prototype method after the instance was replaced with a plain object.
Common situations: Extracting methods into callbacks (e.g. `arr.map(map.get)`) without binding; applying Map methods via .call/.apply to plain objects; refactors that lost the receiver.
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
- Method Generator.prototype called on incompatible receiver
- Constructor Map requires 'new'
- Map.prototype.set is not callable
- Iterator value is not an entry object
- Map.prototype.forEach: callback is not a function
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/9dd8b1c48bd75557.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsMapPrototype.java:68
install("keys", 0, this::keys);
install("values", 0, this::values);
JsBuiltinMethod entries = new JsBuiltinMethod("entries", 0, this::entriesMethod);
install("entries", entries);
// Spec @@iterator on Map.prototype === Map.prototype.entries — same
// wrapped instance keeps identity.
install(IterUtils.SYMBOL_ITERATOR, entries);
// ES2025 upsert proposal — Map.prototype.{getOrInsert, getOrInsertComputed}.
install("getOrInsert", 2, this::getOrInsert);
install("getOrInsertComputed", 2, this::getOrInsertComputed);
installConstructor("Map");
}
private static JsMap asMap(Context context) {
Object thisObj = context.getThisObject();
if (thisObj instanceof JsMap m) {
return m;
}
throw JsErrorException.typeError("Method Map.prototype called on incompatible receiver");
}
private Object get(Context context, Object[] args) {
return asMap(context).getValue(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
private Object set(Context context, Object[] args) {
JsMap m = asMap(context);
Object key = args.length > 0 ? args[0] : Terms.UNDEFINED;
Object value = args.length > 1 ? args[1] : Terms.UNDEFINED;
m.setValue(key, value);
return m;
}
private Object has(Context context, Object[] args) {
return asMap(context).hasKey(args.length > 0 ? args[0] : Terms.UNDEFINED);
}
View on GitHub (pinned to a22eb90246)