karatelabs/karate · error · JsErrorException

toString() radix must be between 2 and 36

Error message

toString() radix must be between 2 and 36

What it means

BigInt.prototype.toString(radix) requires the radix to be an integer between 2 and 36 inclusive; anything else throws this RangeError, mirroring Number.prototype.toString's restriction. Karate's JS engine applies the same bound after the BigInt-radix TypeError check.

Solutions

  1. Clamp/validate: if (!Number.isInteger(r) || r < 2 || r > 36) r = 10
  2. Use base36 (the maximum) plus a custom table for encodings beyond 36
  3. For base64/base58 use a real encoder, not toString(radix)
  4. Default the radix when undefined/invalid rather than passing it through

Example fix

// before
let s = id.toString(58); // RangeError
// after
let s = !Number.isInteger(r) || r < 2 || r > 36 ? id.toString() : id.toString(r);
Defensive patterns

Strategy: validation

Validate before calling

function bigIntToString(n, radix) {
  if (radix === undefined) return n.toString();
  if (!Number.isInteger(radix) || radix < 2 || radix > 36) throw new RangeError('radix must be 2-36');
  return n.toString(radix);
}

Type guard

const isValidRadix = (r) => Number.isInteger(r) && r >= 2 && r <= 36;

Try / catch

let s;
try { s = n.toString(radix); } catch (e) {
  if (e instanceof RangeError && /2 and 36/.test(e.message)) s = n.toString();
  else throw e;
}

Prevention

When it happens

Trigger: x.toString(1), x.toString(0), x.toString(37), x.toString(64), or x.toString(2.5); x.toString(radixFromConfig) with an unsupported base.

Common situations: Attempting base64/base58 encodings via toString; radix read from configuration as 0 or 1; typos like toString(16.) or negative radices; custom numeric encodings assuming unbounded bases.

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


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsBigIntPrototype.java:63

        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;
        }
        if (thisObj instanceof BigInteger bi) {
            return bi;
        }

View on GitHub (pinned to a22eb90246)