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

  1. Bind the method: `const get = map.get.bind(map)`
  2. Use arrow wrappers: `arr.map(k => map.get(k))`
  3. Ensure .call/.apply receivers are real `new Map()` instances
  4. 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

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


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)