karatelabs/karate · error · JsErrorException

invalid hint to Symbol.toPrimitive:

Error message

invalid hint to Symbol.toPrimitive: 

What it means

Date.prototype[Symbol.toPrimitive] accepts only the hints 'string', 'default', or 'number'; any other hint throws this TypeError. Karate's JS engine normalizes 'default' to string-first behavior and rejects everything else before delegating to ordinaryToPrimitive.

Solutions

  1. Use only 'string', 'number', or 'default' as the hint argument
  2. Replace direct Symbol.toPrimitive calls with explicit conversions: String(d), Number(d), d.toString()
  3. Normalize the hint yourself before calling: hint = ['string','number'].includes(hint) ? hint : 'default'
  4. Debug the caller passing the hint and fix it at the source

Example fix

// before
let s = d[Symbol.toPrimitive]('date'); // TypeError
// after
let s = d[Symbol.toPrimitive](hint === 'number' ? 'number' : 'default');
Defensive patterns

Strategy: validation

Validate before calling

function toPrimitiveHint(d, hint) {
  const ok = ['string', 'number', 'default'];
  if (!ok.includes(hint)) throw new TypeError('hint must be string, number, or default');
  return d[Symbol.toPrimitive](hint);
}

Type guard

const isValidHint = (h) => h === 'string' || h === 'number' || h === 'default';

Try / catch

let v;
try { v = d[Symbol.toPrimitive](hint); } catch (e) {
  if (e instanceof TypeError && /invalid hint/.test(e.message)) v = String(d);
  else throw e;
}

Prevention

When it happens

Trigger: Invoking the well-known Symbol.toPrimitive directly with a fabricated hint: d[Symbol.toPrimitive]('custom'), d[Symbol.toPrimitive](''), or generic toPrimitive plumbing passing through an unexpected hint value.

Common situations: Custom primitive-coercion utilities written against V8's more forgiving internals; metaprogramming frameworks that synthesize hints; test harnesses probing engine edge cases; typos in hand-rolled coercion code.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

    }

    /**
     * Spec §21.4.4.45 Date.prototype[@@toPrimitive](hint).
     * - "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);

View on GitHub (pinned to a22eb90246)