karatelabs/karate · error · TypeError

Invalid value used as weak map key

Error message

Invalid value used as weak map key

What it means

JavaScript's WeakMap can only hold keys that the garbage collector can track: objects, or symbols registered in a global symbol registry (per spec, non-registered symbols are also rejected). Karate's JsWeakMap enforces this via canBeHeldWeakly(key) and throws a TypeError when set() is given a primitive like a number, string, or undefined. This matches V8's own 'Invalid value used as weak map key' TypeError.

Solutions

  1. Use an object (or a registered symbol via Symbol.for) as the key: weakMap.set(keyObj, value).
  2. If you need primitive keys, use a regular Map instead of WeakMap.
  3. Guard the key before calling set: only pass values where typeof k === 'object' ? k !== null : typeof k === 'function' (or registered symbols).
  4. Check for null/undefined key variables upstream — often a failed lookup returned undefined.

Example fix

// before
const cache = new WeakMap();
cache.set(userId, profile); // TypeError: primitive key

// after
const cache = new Map();          // primitives allowed
cache.set(userId, profile);
Defensive patterns

Strategy: validation

Validate before calling

function isWeakKey(k) { return (typeof k === 'object' && k !== null) || typeof k === 'function' || (typeof k === 'symbol' && k === Symbol.for(String(k))); }
if (!isWeakKey(key)) throw new Error('weak map key must be an object');
wm.set(key, value);

Type guard

function isWeakKey(k) { return (typeof k === 'object' && k !== null) || typeof k === 'function'; }

Prevention

When it happens

Trigger: Calling weakMap.set(key, value) where key is a primitive (number, string, boolean, null, undefined, bigint, or an unregistered symbol), e.g. new WeakMap().set(42, 'x') or new WeakMap().set('id', obj).

Common situations: Migrating code from Map to WeakMap where keys were string IDs; JSON-deserialized data where keys came back as strings instead of object references; accidental use of undefined because the key variable was never assigned.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsWeakMap.java:67

    /** Spec CanBeHeldWeakly: objects only. Real WeakMaps also accept
     *  non-registered symbols, but this engine has no symbol primitive. */
    static boolean canBeHeldWeakly(Object value) {
        return !Terms.isPrimitive(value);
    }

    boolean hasKey(Object key) {
        return canBeHeldWeakly(key) && entries.containsKey(key);
    }

    Object getValue(Object key) {
        // containsKey, not get() == null — a stored JS null is a Java null value
        // and must not read back as undefined.
        return hasKey(key) ? entries.get(key) : Terms.UNDEFINED;
    }

    void setValue(Object key, Object value) {
        if (!canBeHeldWeakly(key)) {
            throw JsErrorException.typeError("Invalid value used as weak map key");
        }
        entries.put(key, value);
    }

    boolean deleteKey(Object key) {
        if (!hasKey(key)) {
            return false;
        }
        entries.remove(key);
        return true;
    }

}

View on GitHub (pinned to a22eb90246)