karatelabs/karate · error · TypeError
Set-like object's 'has' is not callable
Error message
Set-like object's 'has' is not callable
What it means
While constructing a SetRecord from a Set-like object, its `has` member was not callable. The spec requires the Set-like to expose callable has and keys methods for difference/intersection to probe membership.
Solutions
- Provide a callable has member on the Set-like object.
- Use a real Set, which always has callable has/keys.
- Verify Object.keys(other) includes 'has' and typeof other.has === 'function' before calling.
Example fix
// before
const like = { size: 1, keys: () => ['a'][Symbol.iterator]() };
mySet.difference(like);
// after
const like = { size: 1, has: k => k === 'a', keys: () => ['a'][Symbol.iterator]() };
mySet.difference(like); Defensive patterns
Strategy: validation
Validate before calling
if (typeof other?.has !== 'function' || typeof other?.keys !== 'function') throw new TypeError('Set-like must have callable has and keys'); Type guard
function isCallableSetLike(v) { return v !== null && typeof v === 'object' && typeof v.has === 'function' && typeof v.keys === 'function'; } Try / catch
try { return mySet.difference(other); } catch (e) { if (String(e).includes("'has' is not callable")) return mySet.difference(new Set()); throw e; } Prevention
- Implement has, keys, and size together on custom Set-likes.
- Check property names — it is `has`, not `contains`.
- Prefer real Set instances to avoid manual protocol conformance.
When it happens
Trigger: set.difference({ size: 2, has: true, keys: fn }); or the Set-like is missing `has` entirely (undefined).
Common situations: Partially implemented Set-like objects (size and keys present, has forgotten); property name typos (e.g. `contains` instead of `has`); passing a plain Map (which has no `has`-as-own-member semantics the caller expects in that shape).
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
- Set-like object's size is not a number
- Constructor Set requires 'new'
- Method Set.prototype called on incompatible receiver
- NoSuchElementException
- Set-like object's 'keys' is not callable
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/dc70f5e9b5d85201.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsSetPrototype.java:181
Object rawSize = obj.getMember("size", obj, cc);
Number numSize = Terms.toNumberCoerce(rawSize, cc);
double d = numSize.doubleValue();
if (Double.isNaN(d)) {
throw JsErrorException.typeError("Set-like object's size is not a number");
}
// ToIntegerOrInfinity, then RangeError on negative — spec step 7.
long intSize;
if (Double.isInfinite(d)) {
intSize = d > 0 ? Long.MAX_VALUE : Long.MIN_VALUE;
} else {
intSize = (long) d;
}
if (intSize < 0) {
throw JsErrorException.rangeError("Set-like object's size is negative");
}
Object hasFn = obj.getMember("has", obj, cc);
if (!(hasFn instanceof JsCallable has)) {
throw JsErrorException.typeError("Set-like object's 'has' is not callable");
}
Object keysFn = obj.getMember("keys", obj, cc);
if (!(keysFn instanceof JsCallable keys)) {
throw JsErrorException.typeError("Set-like object's 'keys' is not callable");
}
return new SetRecord(obj, intSize, has, keys);
}
private static JsIterator keysIter(SetRecord rec, Context ctx) {
return IterUtils.iteratorFromCallable(rec.keys, rec.setObj, ctx);
}
/** Spec normalize: -0 → +0 on values pulled from a foreign keys() iteration. */
private static Object normalize(Object v) {
return JsMap.normalizeKey(v);
}
/** Direct-populate a JsSet, bypassing Set.prototype.add per spec. */View on GitHub (pinned to a22eb90246)