karatelabs/karate · error · JsErrorException

Invalid time value

Error message

Invalid time value

What it means

toISOString() must produce a valid ISO-8601 string, which is impossible for an invalid date (the internal time value is NaN, e.g. from new Date(NaN) or new Date('garbage')). Karate throws this RangeError per spec §20.4.4.36 step 3 instead of emitting 'Invalid Date' like toString() does.

Solutions

  1. Check isNaN(date.getTime()) before calling toISOString() and handle the invalid case.
  2. Sanitize/validate the date input string or number before constructing the Date.
  3. Fall back to String(date) ('Invalid Date') or a sentinel like null when serialization is needed.

Example fix

// before
const iso = new Date(input).toISOString(); // RangeError on bad input
// after
const d = new Date(input);
const iso = isNaN(d.getTime()) ? null : d.toISOString();
Defensive patterns

Strategy: validation

Validate before calling

const d = new Date(input); if (isNaN(d.getTime())) throw new Error('invalid date: ' + input);

Type guard

function isValidDate(v) { return v instanceof Date && !isNaN(v.getTime()); }

Try / catch

try { return d.toISOString(); } catch (e) { if (e instanceof RangeError && /Invalid time value/.test(e.message)) return null; throw e; }

Prevention

When it happens

Trigger: new Date(NaN).toISOString(), new Date('not-a-date').toISOString(), new Date(Infinity).toISOString(), or any Date whose valueOf() is NaN flowing into JSON.stringify (which calls toJSON -> toISOString).

Common situations: Parsing untrusted/invalid date strings from API responses or user input, arithmetic like date + undefined yielding NaN, JSON.stringify of an object holding an invalid Date.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/d8bd6180c4b4cff3. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsDatePrototype.java:191

        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);
    }

    /**
     * Spec Date.prototype.toJSON: works on ANY object (not just Date) per
     * §21.4.4.37. ToPrimitive(this, hint Number); if Number+non-finite return null;
     * else Invoke(O, "toISOString"). The unusual generic-this pattern is why
     * this method does NOT use {@link #requireDate}.
     */

View on GitHub (pinned to a22eb90246)