{"record":{"id":"dc70f5e9b5d85201","repo":"karatelabs/karate","slug":"set-like-object-s-has-is-not-callable","errorCode":null,"errorMessage":"Set-like object's 'has' is not callable","messagePattern":"Set-like object's 'has' is not callable","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsSetPrototype.java","lineNumber":181,"sourceCode":"        Object rawSize = obj.getMember(\"size\", obj, cc);\n        Number numSize = Terms.toNumberCoerce(rawSize, cc);\n        double d = numSize.doubleValue();\n        if (Double.isNaN(d)) {\n            throw JsErrorException.typeError(\"Set-like object's size is not a number\");\n        }\n        // ToIntegerOrInfinity, then RangeError on negative — spec step 7.\n        long intSize;\n        if (Double.isInfinite(d)) {\n            intSize = d > 0 ? Long.MAX_VALUE : Long.MIN_VALUE;\n        } else {\n            intSize = (long) d;\n        }\n        if (intSize < 0) {\n            throw JsErrorException.rangeError(\"Set-like object's size is negative\");\n        }\n        Object hasFn = obj.getMember(\"has\", obj, cc);\n        if (!(hasFn instanceof JsCallable has)) {\n            throw JsErrorException.typeError(\"Set-like object's 'has' is not callable\");\n        }\n        Object keysFn = obj.getMember(\"keys\", obj, cc);\n        if (!(keysFn instanceof JsCallable keys)) {\n            throw JsErrorException.typeError(\"Set-like object's 'keys' is not callable\");\n        }\n        return new SetRecord(obj, intSize, has, keys);\n    }\n\n    private static JsIterator keysIter(SetRecord rec, Context ctx) {\n        return IterUtils.iteratorFromCallable(rec.keys, rec.setObj, ctx);\n    }\n\n    /** Spec normalize: -0 → +0 on values pulled from a foreign keys() iteration. */\n    private static Object normalize(Object v) {\n        return JsMap.normalizeKey(v);\n    }\n\n    /** Direct-populate a JsSet, bypassing Set.prototype.add per spec. */","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsSetPrototype.java#L163-L199","documentation":"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.","triggerScenarios":"set.difference({ size: 2, has: true, keys: fn }); or the Set-like is missing `has` entirely (undefined).","commonSituations":"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).","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."],"exampleFix":"// before\nconst like = { size: 1, keys: () => ['a'][Symbol.iterator]() };\nmySet.difference(like);\n// after\nconst like = { size: 1, has: k => k === 'a', keys: () => ['a'][Symbol.iterator]() };\nmySet.difference(like);","handlingStrategy":"validation","validationCode":"if (typeof other?.has !== 'function' || typeof other?.keys !== 'function') throw new TypeError('Set-like must have callable has and keys');","typeGuard":"function isCallableSetLike(v) { return v !== null && typeof v === 'object' && typeof v.has === 'function' && typeof v.keys === 'function'; }","tryCatchPattern":"try { return mySet.difference(other); } catch (e) { if (String(e).includes(\"'has' is not callable\")) return mySet.difference(new Set()); throw e; }","preventionTips":["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."],"tags":["javascript","set","set-like"],"backgroundTag":"invalid-argument-value","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}