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

  1. Ensure the receiver is a Date object (or any object): call the method as `someDate[Symbol.toPrimitive]('number')` rather than detached.
  2. Use Function.prototype.call with an object as the first argument: Date.prototype[Symbol.toPrimitive].call(new Date(), 'number').
  3. 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

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


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)