karatelabs/karate · error · JsErrorException (typeError)

Cannot mix BigInt and other types, use explicit conversions…

Error message

Cannot mix BigInt and other types, use explicit conversions (+)

What it means

JS forbids using `+` (or the other arithmetic operators) between a BigInt and any other type, including numbers and strings-as-numbers. Terms.java's add operator detects a mixed BigInt operand pair and throws this TypeError, exactly like V8.

Solutions

  1. Convert explicitly on the JS side: use Number(x) or BigInt(x) so both operands match
  2. Use BigInt for both operands if precision matters: 1n + BigInt(jsonValue)
  3. If the intent is string concat, convert with String(bigintValue) + otherString

Example fix

// before
var sum = countN + delta;
// after
var sum = countN + BigInt(delta); // or Number(countN) + delta
Defensive patterns

Strategy: type-guard

Validate before calling

if ((typeof a === 'bigint') !== (typeof b === 'bigint')) throw new Error('mixed BigInt/non-BigInt operands');

Type guard

function bothBigInt(a, b) { return typeof a === 'bigint' && typeof b === 'bigint'; }

Try / catch

try { sum = a + b; } catch (e) { if (String(e).includes('Cannot mix BigInt')) sum = Number(a) + Number(b); else throw e; }

Prevention

When it happens

Trigger: Evaluating `1n + 1`, `1n + '2'`, or any `a + b` in karate-js where exactly one operand is a BigInteger.

Common situations: Mixing values that came from BigInt literals with values parsed from JSON/numbers (JSON never produces BigInt), or string concatenation where one side is BigInt from a helper.

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/f50e53d8dd90c8bd. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/Terms.java:835

    static Object add(Object lhs, Object rhs, CoreContext context) {
        // Spec evaluation of binary +: ToPrimitive both operands first (default hint),
        // then string-or-number dispatch on the *primitives*. ObjectLike on either side
        // is the rare case — primitives short-circuit through the existing fast path.
        if (lhs instanceof ObjectLike) {
            lhs = toPrimitive(lhs, "default", context);
            if (context != null && context.isError()) return UNDEFINED;
        }
        if (rhs instanceof ObjectLike) {
            rhs = toPrimitive(rhs, "default", context);
            if (context != null && context.isError()) return UNDEFINED;
        }
        if (lhs instanceof String || rhs instanceof String) {
            return concatOperand(lhs) + concatOperand(rhs);
        }
        // BigInt branch — pulled into a fast type test that fails on the common case
        if (lhs instanceof BigInteger || rhs instanceof BigInteger) {
            if (!(lhs instanceof BigInteger) || !(rhs instanceof BigInteger)) {
                throw JsErrorException.typeError(
                    "Cannot mix BigInt and other types, use explicit conversions (+)");
            }
            return narrowBigInt(((BigInteger) lhs).add((BigInteger) rhs));
        }
        Number lhsNum = objectToNumber(lhs);
        Number rhsNum = objectToNumber(rhs);
        double result = lhsNum.doubleValue() + rhsNum.doubleValue();
        return narrow(result);
    }

    private static String concatOperand(Object o) {
        if (o instanceof String s) return s;
        if (o instanceof Number n) return numberToString(n);
        return String.valueOf(o);
    }

    // BigInt does NOT participate in `narrow` (which collapses to int/long/double).
    // Returning the BigInteger as-is preserves the bigint type identity through

View on GitHub (pinned to a22eb90246)