{"record":{"id":"8e47c673cdb21529","repo":"karatelabs/karate","slug":"tosorted-comparator-must-be-a-function","errorCode":null,"errorMessage":"toSorted comparator must be a function","messagePattern":"toSorted comparator must be a function","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsArrayPrototype.java","lineNumber":1158,"sourceCode":"        if (target == null) return Terms.UNDEFINED;\n        int len = lengthOf(target, cc);\n        if (cc != null && cc.isError()) return Terms.UNDEFINED;\n        List<Object> result = new ArrayList<>(checkResultLength(len));\n        for (int k = 0; k < len; k++) {\n            result.add(specGet(target, String.valueOf(len - k - 1), cc));\n        }\n        return new JsArray(result);\n    }\n\n    /**\n     * Spec §23.1.3.35 Array.prototype.toSorted (ES2023). Same SortCompare as\n     * {@link #sort} but writes to a fresh array; source is untouched. Holes\n     * are read through the proto chain (treated as undefined for the sort).\n     */\n    private Object toSorted(Context context, Object[] args) {\n        if (args.length > 0 && args[0] != Terms.UNDEFINED && args[0] != null\n                && !(args[0] instanceof JsCallable)) {\n            throw JsErrorException.typeError(\"toSorted comparator must be a function\");\n        }\n        CoreContext cc = context instanceof CoreContext cx ? cx : null;\n        ObjectLike target = toReceiver(context.getThisObject());\n        if (target == null) return Terms.UNDEFINED;\n        int len = lengthOf(target, cc);\n        if (cc != null && cc.isError()) return Terms.UNDEFINED;\n        List<Object> items = new ArrayList<>(checkResultLength(len));\n        for (int k = 0; k < len; k++) {\n            items.add(specGet(target, String.valueOf(k), cc));\n        }\n        JsCallable comparator = (args.length > 0 && args[0] instanceof JsCallable jc) ? jc : null;\n        items.sort((a, b) -> {\n            boolean aUndef = a == null || a == Terms.UNDEFINED;\n            boolean bUndef = b == null || b == Terms.UNDEFINED;\n            if (aUndef && bUndef) return 0;\n            if (aUndef) return 1;\n            if (bUndef) return -1;\n            if (comparator != null) {","sourceCodeStart":1140,"sourceCodeEnd":1176,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsArrayPrototype.java#L1140-L1176","documentation":"Array.prototype.toSorted accepts either no argument or a comparator function; per spec, any other value (except undefined) must throw. Karate throws TypeError 'toSorted comparator must be a function' when args[0] is present, not null/undefined, and not a JsCallable.","triggerScenarios":"arr.toSorted('name'); arr.toSorted(1); arr.toSorted({}); — i.e. a non-callable, non-undefined first argument to toSorted (unlike sort, passing null/undefined is tolerated here).","commonSituations":"Confusing toSorted with toSorted-by-key helpers from other libraries (e.g. lodash-style sortBy('field')); porting code that sorted by property name strings; accidentally passing a mapped key instead of a comparator.","solutions":["Pass a comparator function: arr.toSorted((a, b) => a.name.localeCompare(b.name))","Replace string key usage with a comparator that reads the key","Drop the argument entirely for default (string) sorting","Map the key first: arr.map(x => x.key).toSorted()"],"exampleFix":"// before\nconst sorted = users.toSorted('name');\n// after\nconst sorted = users.toSorted((a, b) => a.name.localeCompare(b.name));","handlingStrategy":"type-guard","validationCode":"if (cmp !== undefined && cmp !== null && typeof cmp !== 'function') throw new Error('comparator must be a function');","typeGuard":"function isComparator(x) { return x == null || typeof x === 'function'; }","tryCatchPattern":"try { return arr.toSorted(cmp); } catch (e) { if (String(e.message).includes('comparator must be a function')) return arr.toSorted((a,b) => String(a).localeCompare(String(b))); throw e; }","preventionTips":["Remember toSorted takes a comparator function, not a key string","Use lodash-style sortBy for key-based sorting instead","Coerce undefined comparator explicitly before calling"],"tags":["javascript","array","sorting","type-error"],"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"}