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
- Use an object (or a registered symbol via Symbol.for) as the key: weakMap.set(keyObj, value).
- If you need primitive keys, use a regular Map instead of WeakMap.
- Guard the key before calling set: only pass values where typeof k === 'object' ? k !== null : typeof k === 'function' (or registered symbols).
- 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
- Use Map for primitive keys, WeakMap only for object-keyed metadata
- Never pass JSON-derived values as WeakMap keys without checking type
- Validate key variables are defined before set()
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
- Constructor WeakMap requires 'new'
- WeakMap.prototype.set is not callable
- Iterator value is not an entry object
- Method WeakMap.prototype called on incompatible receiver
- Cannot set property ' ' which has only a getter
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)