karatelabs/karate · error · TypeError

WeakSet.prototype.add is not callable

Error message

WeakSet.prototype.add is not callable

What it means

When building a WeakSet from an iterable, the constructor resolves the set's 'add' method to use as the adder. If getMember("add") does not yield a JsCallable, Karate throws this TypeError rather than continuing, mirroring the spec's internal Adder creation failure.

Solutions

  1. Leave WeakSet.prototype.add intact; undo any overwrites or deletions.
  2. Restore from a saved reference: WeakSet.prototype.add = originalAdd.
  3. Construct empty and call add() explicitly instead of passing an iterable.
  4. Remove any code assigning non-function values to WeakSet.prototype members.

Example fix

// before
delete WeakSet.prototype.add;
const ws = new WeakSet([obj]); // TypeError

// after
const ws = new WeakSet();
ws.add(obj);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof WeakSet.prototype.add !== 'function') throw new Error('WeakSet.prototype.add was clobbered');

Try / catch

try { var ws = new WeakSet(values); } catch (e) { var ws2 = new WeakSet(); values.forEach(v => ws2.add(v)); }

Prevention

When it happens

Trigger: new WeakSet(iterable) where the instance's 'add' member is not a JsCallable — e.g. WeakSet.prototype.add was overwritten with a non-function, deleted, or shadowed earlier in the script.

Common situations: Monkey-patching WeakSet.prototype.add and getting it wrong; deleting prototype methods; proxy/reflection experiments in embedded JS that break member lookup.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/6a72e4b3403a8884. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsWeakSetConstructor.java:52

    JsWeakSetConstructor() {
        this.name = "WeakSet";
        defineOwn("prototype", JsWeakSetPrototype.INSTANCE, PropertySlot.INTRINSIC);
    }

    @Override
    public Object call(Context context, Object[] args) {
        CallInfo callInfo = context.getCallInfo();
        boolean isNew = callInfo != null && callInfo.constructor;
        if (!isNew) {
            throw JsErrorException.typeError("Constructor WeakSet requires 'new'");
        }
        JsWeakSet set = new JsWeakSet();
        if (args.length == 0 || args[0] == null || args[0] == Terms.UNDEFINED) {
            return set;
        }
        Object addFn = set.getMember("add");
        if (!(addFn instanceof JsCallable adder)) {
            throw JsErrorException.typeError("WeakSet.prototype.add 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 v = iter.next();
                if (cc != null) cc.thisObject = set;
                adder.call(context, new Object[]{v});
                if (cc != null && cc.isError()) {
                    return set;
                }
            }
        } finally {
            if (cc != null) cc.thisObject = savedThis;
        }
        return set;
    }

View on GitHub (pinned to a22eb90246)