karatelabs/karate · error · JsErrorException
Cannot convert a BigInt to a number
Error message
Cannot convert a BigInt to a number
What it means
BigInt.prototype.toString(radix) rejects a BigInt radix argument with a TypeError because the spec's ToIntegerOrInfinity step cannot convert BigInt to Number. Karate's JS engine enforces this ordering deliberately (TypeError before any RangeError), as noted in the source comment.
Solutions
- Pass a plain Number radix: x.toString(16) not x.toString(16n)
- Convert with Number(radix) after confirming it is a small safe integer: x.toString(Number(radix))
- Keep radix constants as JS numbers, not BigInt literals
- Guard: if (typeof radix === 'bigint') radix = Number(radix)
Example fix
// before let hex = value.toString(RADIX); // RADIX = 16n // after let hex = value.toString(Number(RADIX)); // 16
Defensive patterns
Strategy: type-guard
Validate before calling
function bigIntToString(n, radix) {
if (typeof radix === 'bigint') radix = Number(radix);
if (radix !== undefined && (!Number.isInteger(radix) || radix < 2 || radix > 36)) throw new RangeError('radix out of range');
return radix === undefined ? n.toString() : n.toString(radix);
} Type guard
const isNumberRadix = (r) => typeof r === 'number' && Number.isSafeInteger(r);
Try / catch
let s;
try { s = n.toString(radix); } catch (e) {
if (e instanceof TypeError && /BigInt to a number/.test(e.message)) s = n.toString(Number(radix));
else throw e;
} Prevention
- Keep radix constants as plain Number literals (16, not 16n)
- Coerce BigInt-derived values with Number() before using as radix
- Never copy BigInt literals wholesale from generated/migrated code
- Lint for BigInt literals used in numeric-parameter positions
When it happens
Trigger: x.toString(2n), x.toString(radixBig) where radix was itself computed as a BigInt (e.g. from BigInt arithmetic or parsed as a BigInt literal), n.toString(BigInt(16)).
Common situations: Mixed BigInt/Number math pipelines where the radix variable was derived from BigInt operations; porting code where literals became 16n instead of 16; generated code emitting BigInt literals for all numeric constants.
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 object to a BigInt
- toString() radix must be between 2 and 36
- BigInt.prototype method called on non-BigInt
- Cannot mix BigInt and other types, use explicit conversions
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/899f626b4d825441.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsBigIntPrototype.java:59
install("toLocaleString", 0, this::toStringMethod);
}
private Object toStringMethod(Context context, Object[] args) {
BigInteger n = asBigInt(context);
// Spec: only `undefined` (or absent) defaults to radix 10; `null` runs through
// ToInteger → 0 → RangeError. Same shape as Number.prototype.toString.
if (args.length > 0 && args[0] != Terms.UNDEFINED) {
Object radixArg = args[0];
// Object → ToPrimitive (hint "number"). If valueOf/toString are non-callable
// ToPrimitive throws TypeError (per spec); error flows through context for
// user-thrown valueOf bodies.
if (radixArg instanceof ObjectLike && context instanceof CoreContext cc) {
radixArg = Terms.toPrimitive(radixArg, "number", cc);
if (cc.isError()) return Terms.UNDEFINED;
}
// ToIntegerOrInfinity rejects BigInt — spec mandates TypeError before RangeError.
if (radixArg instanceof BigInteger) {
throw JsErrorException.typeError("Cannot convert a BigInt to a number");
}
int radix = Terms.objectToNumber(radixArg).intValue();
if (radix < 2 || radix > 36) {
throw JsErrorException.rangeError("toString() radix must be between 2 and 36");
}
return n.toString(radix);
}
return n.toString();
}
private Object valueOf(Context context, Object[] args) {
return asBigInt(context);
}
private static BigInteger asBigInt(Context context) {
Object thisObj = context.getThisObject();
if (thisObj instanceof JsBigInt jb) {
return jb.value;View on GitHub (pinned to a22eb90246)