karatelabs/karate · error · JsErrorException
ToIndex: value must be non-negative
Error message
ToIndex: value must be non-negative
What it means
BigInt.asIntN(bits, value) and BigInt.asUintN coerce their first argument through the spec's ToIndex, which requires an integral, non-negative number. A negative number (or any number truncating below zero) throws this RangeError in Karate's JS engine.
Solutions
- Clamp the width before the call: BigInt.asIntN(Math.max(0, w), v)
- Validate w is a non-negative integer: if (!Number.isInteger(w) || w < 0) throw new RangeError('bad width')
- Check argument order — bits come first, the BigInt second
- Sanitize config-sourced widths at load time with defaults (w = Number.isInteger(cfg.width) && cfg.width >= 0 ? cfg.width : 32)
Example fix
// before let masked = BigInt.asIntN(bits, value); // bits = -8 from config // after let masked = BigInt.asIntN(Math.max(0, bits | 0), value);
Defensive patterns
Strategy: validation
Validate before calling
function asIntNSafe(bits, value) {
if (!Number.isInteger(bits) || bits < 0) throw new RangeError('bits must be a non-negative integer');
return BigInt.asIntN(bits, value);
} Try / catch
let masked;
try { masked = BigInt.asIntN(bits, v); } catch (e) {
if (e instanceof RangeError && /non-negative/.test(e.message)) masked = BigInt.asIntN(64, v);
else throw e;
} Prevention
- Validate bit widths from config/env as non-negative integers at load time
- Remember argument order: bits first, BigInt second
- Clamp computed widths with Math.max(0, w)
- Unit-test width arithmetic (subtractions) that can go negative
When it happens
Trigger: BigInt.asIntN(-1, 5n), BigInt.asIntN(width, x) where width is a negative computed variable, BigInt.asUintN(size - overflow, v) with a size smaller than the subtracted amount.
Common situations: Bit-width read from config/environment that is unset or negative; arithmetic like maxWidth - padding going negative; copy-pasted code passing the value as the first argument instead of the bit count.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Cannot convert non-finite number to BigInt
- Cannot convert non-integer number to BigInt
- toString() radix must be between 2 and 36
- Cannot convert a BigInt to a number using unary +
- array index too large for dense storage:
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/3de7b96ffeae50ba.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsBigIntConstructor.java:159
if (bits == 0) return BigInteger.ZERO;
BigInteger mod = BigInteger.ONE.shiftLeft(bits);
return bi.mod(mod);
}
// Spec ToIndex: ToPrimitive("number") → ToNumber → ToInteger, then RangeError if
// negative. Truncate fires *before* the negative check, so -0.9 → 0 (not RangeError).
// NaN / undefined / null / false / "" all collapse to 0.
private static int toIndex(Object value, CoreContext context) {
if (value instanceof ObjectLike) {
value = Terms.toPrimitive(value, "number", context);
if (context != null && context.isError()) return 0;
}
Number n = Terms.objectToNumber(value);
double d = n.doubleValue();
if (Double.isNaN(d) || d == 0) return 0;
long truncated = (long) d; // Java cast: truncate toward zero
if (truncated < 0) {
throw JsErrorException.rangeError("ToIndex: value must be non-negative");
}
return (int) truncated;
}
}
View on GitHub (pinned to a22eb90246)