{"record":{"id":"57ba71163ed0136f","repo":"karatelabs/karate","slug":"date-prototype-toprimitive-called-on-non-object","errorCode":null,"errorMessage":"Date.prototype[@@toPrimitive] called on non-object","messagePattern":"Date\\.prototype\\[@@toPrimitive\\] called on non-object","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsDatePrototype.java","lineNumber":183,"sourceCode":"     * - \"string\" / \"default\" → OrdinaryToPrimitive(this, \"string\")\n     * - \"number\"             → OrdinaryToPrimitive(this, \"number\")\n     * - anything else        → TypeError\n     * The \"default\" → \"string\" override is the whole point of Date having its own\n     * @@toPrimitive: it makes `new Date() + \"\"` string-concat instead of timestamp-add.\n     */\n    private Object toPrimitive(Context context, Object[] args) {\n        Object hint = args.length > 0 ? args[0] : Terms.UNDEFINED;\n        String h;\n        if (\"string\".equals(hint) || \"default\".equals(hint)) {\n            h = \"string\";\n        } else if (\"number\".equals(hint)) {\n            h = \"number\";\n        } else {\n            throw JsErrorException.typeError(\"invalid hint to Symbol.toPrimitive: \" + hint);\n        }\n        Object thisObj = context.getThisObject();\n        if (!(thisObj instanceof ObjectLike ol)) {\n            throw JsErrorException.typeError(\"Date.prototype[@@toPrimitive] called on non-object\");\n        }\n        return Terms.ordinaryToPrimitive(ol, h, (CoreContext) context);\n    }\n\n    private Object toISOString(Context context, Object[] args) {\n        JsDate d = requireDate(context);\n        if (d.isInvalid()) {\n            throw JsErrorException.rangeError(\"Invalid time value\");\n        }\n        return formatIso(d);\n    }\n\n    private Object toUTCString(Context context, Object[] args) {\n        JsDate d = requireDate(context);\n        if (d.isInvalid()) {\n            return \"Invalid Date\";\n        }\n        return formatUtc(d);","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsDatePrototype.java#L165-L201","documentation":"Date.prototype[@@toPrimitive] is the spec's generic conversion hook, but unlike other Date methods it does not coerce its `this`. Karate's JS engine requires `this` to be an ObjectLike (an actual object); when called on a primitive such as a number, string, boolean, null or undefined it throws this TypeError per spec §20.4.4.46 step 1.","triggerScenarios":"Calling Date.prototype[Symbol.toPrimitive].call(42, 'number'), .call('2024-01-01', 'string'), .call(null, 'default'), or extracting the method and invoking it with a primitive `this` (e.g. `const tp = Date.prototype[Symbol.toPrimitive]; tp('number')`).","commonSituations":"Destructuring or borrowing Date methods onto primitives, applying generic-function tricks from other engines (Node allows some sloppy-mode coercion paths), or passing a raw primitive where a Date object is expected in custom conversion code.","solutions":["Ensure the receiver is a Date object (or any object): call the method as `someDate[Symbol.toPrimitive]('number')` rather than detached.","Use Function.prototype.call with an object as the first argument: Date.prototype[Symbol.toPrimitive].call(new Date(), 'number').","If you have a primitive timestamp, skip toPrimitive and use the value directly or new Date(value).valueOf()."],"exampleFix":"// before\nconst tp = Date.prototype[Symbol.toPrimitive];\nconst n = tp.call(1700000000000, 'number'); // TypeError\n// after\nconst n = new Date(1700000000000)[Symbol.toPrimitive]('number');","handlingStrategy":"type-guard","validationCode":"if (obj === null || typeof obj !== 'object') throw new TypeError('@@toPrimitive needs an object receiver');","typeGuard":"function isToPrimitiveSafe(v) { return v !== null && (typeof v === 'object' || typeof v === 'function'); }","tryCatchPattern":"try { return date[Symbol.toPrimitive]('number'); } catch (e) { if (e instanceof TypeError) return Number(date); throw e; }","preventionTips":["Never detach Symbol.toPrimitive from its receiver; always call it as a method.","When borrowing methods, pass an object receiver via .call/.apply.","Prefer Number(date)/String(date) over manual @@toPrimitive calls."],"tags":["javascript","date","type-error","to-primitive"],"backgroundTag":"type-mismatch","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}