karatelabs/karate · error · JsErrorException

Map.prototype.set is not callable

Error message

Map.prototype.set is not callable

What it means

Karate's JS engine throws this while constructing a Map from an iterable, per spec 24.1.1.1 step 9: it looks up `set` on the new map's prototype chain and requires it to be a callable function. If `Map.prototype.set` was deleted, overwritten with a non-function, or the map instance's prototype was mangled, construction aborts with this TypeError.

Solutions

  1. Restore the built-in: remove any `Map.prototype.set = ...` override or delete it before constructing Maps
  2. Ensure any Map polyfill/shim defines `set` as a function
  3. Check that code does not reassign an object's prototype (`Object.setPrototypeOf`) away from Map.prototype before passing it through `new Map()`
  4. Isolate the mutating script — run the Map construction in a fresh Karate JS context

Example fix

// before
Map.prototype.set = null;
const m = new Map([[1, 'a']]); // TypeError
// after
Map.prototype.set = origSet; // restore or don't override
const m = new Map([[1, 'a']]);
Defensive patterns

Strategy: type-guard

Validate before calling

// before constructing
if (typeof Map.prototype.set !== 'function') {
  throw new Error('Map.prototype.set was clobbered; restore it before new Map(iterable)');
}

Type guard

function mapSetIsCallable() { return typeof Map.prototype.set === 'function'; }

Try / catch

try {
  const m = new Map(iterable);
} catch (e) {
  if (String(e.message).includes('Map.prototype.set is not callable')) {
    // restore built-in / run in clean context
  } else throw e;
}

Prevention

When it happens

Trigger: Passing an iterable to `new Map(iterable)` after user code has done `Map.prototype.set = null` / `delete Map.prototype.set`, or reassigned a Map instance's prototype to a plain object lacking a callable `set`.

Common situations: Monkey-patching Map.prototype in test setup or polyfills that accidentally clobber built-ins; transpilers or DSL code overriding Map methods; running JS that mutates global built-ins before constructing Maps.

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/00810a7028f3791e. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsMapConstructor.java:72

                GroupByImpl.run(items, callback, /* propertyMode= */ false, context));
    }

    @Override
    public Object call(Context context, Object[] args) {
        CallInfo callInfo = context.getCallInfo();
        boolean isNew = callInfo != null && callInfo.constructor;
        if (!isNew) {
            throw JsErrorException.typeError("Constructor Map requires 'new'");
        }
        JsMap map = new JsMap();
        if (args.length == 0 || args[0] == null || args[0] == Terms.UNDEFINED) {
            return map;
        }
        // Look up `set` on the freshly-constructed map's prototype chain — honors
        // user-overridden Map.prototype.set per spec 24.1.1.1 step 9.
        Object setFn = map.getMember("set");
        if (!(setFn instanceof JsCallable adder)) {
            throw JsErrorException.typeError("Map.prototype.set is not callable");
        }
        JsIterator iter = IterUtils.getIterator(args[0], context);
        CoreContext cc = context instanceof CoreContext c ? c : null;
        Object savedThis = cc != null ? cc.thisObject : null;
        try {
            while (iter.hasNext()) {
                Object entry = iter.next();
                if (!(entry instanceof List) && !(entry instanceof ObjectLike)) {
                    throw JsErrorException.typeError("Iterator value " + entry + " is not an entry object");
                }
                Object k;
                Object v;
                if (entry instanceof List<?> list) {
                    k = list.isEmpty() ? Terms.UNDEFINED : list.get(0);
                    v = list.size() < 2 ? Terms.UNDEFINED : list.get(1);
                } else {
                    ObjectLike ol = (ObjectLike) entry;
                    k = ol.getMember("0");

View on GitHub (pinned to a22eb90246)