karatelabs/karate · error · JsErrorException

Cannot convert null or undefined to object

Error message

Cannot convert null or undefined to object

What it means

Date.prototype.toJSON uses the generic-this pattern (it can delegate to any object with a toISOString), but null and undefined have no object wrapper, so it throws this TypeError per spec §20.4.4.37 step 1. Other primitives are accepted and coerced via ToPrimitive.

Solutions

  1. Guard for null/undefined before serializing: only call toJSON / stringify when the value is a Date.
  2. Use a replacer function in JSON.stringify that maps null dates to a safe value.
  3. Fix the data source so the field is always a Date object or explicitly omitted.

Example fix

// before
const s = JSON.stringify({ d: maybeDate }); // TypeError if maybeDate is null via toJSON path
// after
const s = JSON.stringify({ d: maybeDate instanceof Date ? maybeDate : null });
Defensive patterns

Strategy: type-guard

Validate before calling

if (value == null) return null; // skip serialization of absent dates

Type guard

function isDateLike(v) { return v !== null && v !== undefined && typeof v === 'object'; }

Try / catch

try { return JSON.stringify(payload); } catch (e) { if (e instanceof TypeError && /null or undefined/.test(e.message)) return JSON.stringify(withNullDates(payload)); throw e; }

Prevention

When it happens

Trigger: Date.prototype.toJSON.call(null), .call(undefined), or JSON.stringify(null/undefined-derived values reaching the Date.toJSON path; also `null.toJSON()` style access routed through this prototype method.

Common situations: JSON.stringify of records where a Date field is sometimes null/undefined, API responses with missing dates, template code that assumes a field is always a Date.

Related errors


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

Appendix: source

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

    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}.
     */
    private Object toJSON(Context context, Object[] args) {
        Object o = context.getThisObject();
        if (o == null || o == Terms.UNDEFINED) {
            throw JsErrorException.typeError("Cannot convert null or undefined to object");
        }
        CoreContext cc = cc(context);
        Object tv = o;
        if (o instanceof ObjectLike && cc != null) {
            tv = Terms.toPrimitive(o, "number", cc);
            if (cc.isError()) return null;
        } else if (o instanceof JsValue jv) {
            tv = jv.getJsValue();
        }
        if (tv instanceof Number n && !Double.isFinite(n.doubleValue())) {
            return null;
        }
        // Direct shortcut for Date this — produce ISO string. Avoids the generic
        // Invoke(O, "toISOString") path doing a redundant getMember dispatch.
        if (o instanceof JsDate d) {
            return formatIso(d);
        }
        // Invoke O.toISOString()

View on GitHub (pinned to a22eb90246)