karatelabs/karate · error · JsErrorException
Date.prototype[@@toPrimitive] called on non-object
Error message
Date.prototype[@@toPrimitive] called on non-object
What it means
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.
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().
Example fix
// before
const tp = Date.prototype[Symbol.toPrimitive];
const n = tp.call(1700000000000, 'number'); // TypeError
// after
const n = new Date(1700000000000)[Symbol.toPrimitive]('number'); Defensive patterns
Strategy: type-guard
Validate before calling
if (obj === null || typeof obj !== 'object') throw new TypeError('@@toPrimitive needs an object receiver'); Type guard
function isToPrimitiveSafe(v) { return v !== null && (typeof v === 'object' || typeof v === 'function'); } Try / catch
try { return date[Symbol.toPrimitive]('number'); } catch (e) { if (e instanceof TypeError) return Number(date); throw e; } Prevention
- 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.
When it happens
Trigger: 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')`).
Common situations: 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.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- this is not a Date object
- invalid hint to Symbol.toPrimitive:
- Cannot convert null or undefined to object
- toISOString is not a function
- toBytes() argument must be a list of numbers, got
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/57ba71163ed0136f.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsDatePrototype.java:183
* - "string" / "default" → OrdinaryToPrimitive(this, "string")
* - "number" → OrdinaryToPrimitive(this, "number")
* - anything else → TypeError
* The "default" → "string" override is the whole point of Date having its own
* @@toPrimitive: it makes `new Date() + ""` string-concat instead of timestamp-add.
*/
private Object toPrimitive(Context context, Object[] args) {
Object hint = args.length > 0 ? args[0] : Terms.UNDEFINED;
String h;
if ("string".equals(hint) || "default".equals(hint)) {
h = "string";
} else if ("number".equals(hint)) {
h = "number";
} else {
throw JsErrorException.typeError("invalid hint to Symbol.toPrimitive: " + hint);
}
Object thisObj = context.getThisObject();
if (!(thisObj instanceof ObjectLike ol)) {
throw JsErrorException.typeError("Date.prototype[@@toPrimitive] called on non-object");
}
return Terms.ordinaryToPrimitive(ol, h, (CoreContext) context);
}
private Object toISOString(Context context, Object[] args) {
JsDate d = requireDate(context);
if (d.isInvalid()) {
throw JsErrorException.rangeError("Invalid time value");
}
return formatIso(d);
}
private Object toUTCString(Context context, Object[] args) {
JsDate d = requireDate(context);
if (d.isInvalid()) {
return "Invalid Date";
}
return formatUtc(d);View on GitHub (pinned to a22eb90246)