karatelabs/karate · error · JsErrorException
Cannot convert a BigInt to a number using unary +
Error message
Cannot convert a BigInt to a number using unary +
What it means
Thrown when unary `+` is applied to a BigInt value. Per the ECMAScript spec, unary plus performs ToNumber, and there is deliberately no implicit BigInt-to-Number conversion (it would lose precision), so `+bigint` is a TypeError.
Solutions
- Use `Number(bigint)` if an explicit (possibly lossy) conversion is intended.
- Keep the value as BigInt and use BigInt arithmetic instead of coercing to number.
- If string coercion was the goal, use `bigint.toString()`.
Example fix
// before var n = +bigValue; // after var n = Number(bigValue); // explicit, or keep as BigInt
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof v === 'bigint') throw new Error('unary + not allowed on BigInt'); Type guard
function isBigInt(v) { return typeof v === 'bigint' || v instanceof java.math.BigInteger; } Try / catch
try { n = +value; } catch (e) { n = Number(value); } Prevention
- Use Number(x) explicitly for conversions
- Avoid unary + in code that may see BigInt values
- Keep BigInt math in BigInt domain
When it happens
Trigger: Evaluating `+bigintVar` in Karate JS — e.g. `+10n`, `+someBigIntResult` from arithmetic or JSON fields holding big integers.
Common situations: Code that coerces numbers with unary `+` (a common idiom for strings) encountering BigInt values produced by large-integer parsing or BigInt literals.
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
- Cannot convert undefined to a BigInt
- Cannot convert non-finite number to BigInt
- Cannot convert non-integer number to BigInt
- Cannot convert to a BigInt
- Cannot convert object to a BigInt
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/bc4cdb6d43675e41.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/Interpreter.java:2457
private static Object evalMathPreExpr(Node node, CoreContext context) {
Node exprNode = node.get(1).getFirst();
return switch (node.get(0).token.type) {
case PLUS_PLUS -> PropertyAccess.preIncDec(exprNode, context, true);
case MINUS_MINUS -> PropertyAccess.preIncDec(exprNode, context, false);
case MINUS -> {
Object v = eval(exprNode, context);
// Rare path: BigInt unary negation needs to stay in the BigInt domain.
// The plain-Number case below would TypeError because rhs (-1) is Integer.
if (v instanceof java.math.BigInteger bi) {
yield Terms.narrowBigInt(bi.negate());
}
yield Terms.mul(v, -1, context);
}
case PLUS -> {
Object v = eval(exprNode, context);
// Spec: unary + on BigInt is a TypeError (no implicit BigInt → Number).
if (v instanceof java.math.BigInteger) {
throw JsErrorException.typeError("Cannot convert a BigInt to a number using unary +");
}
// Spec ToNumber routes through ToPrimitive (hint=number) for
// objects, so {valueOf: () => 7} returns 7 not NaN.
yield Terms.toNumberCoerce(v, context);
}
default -> throw new RuntimeException("unexpected operator: " + node.getFirst());
};
}
private static Object evalProgram(Node node, CoreContext context) {
// A top-level "use strict" directive makes the whole script strict, and
// must be resolved before hoisting so function objects created here
// capture the right lexical strictness via their declaredContext.
if (!context.strict && hasUseStrictDirective(node)) {
context.strict = true;
}
// Program-scope slot frame: dense storage for let/const confined to
// nested blocks / for-inits at top level (SlotTable.forProgram — theView on GitHub (pinned to a22eb90246)