karatelabs/karate · error · JsErrorException

toExponential() fractionDigits must be between 0 and 100

Error message

toExponential() fractionDigits must be between 0 and 100

What it means

Number.prototype.toExponential accepts fractionDigits in the range 0–100 in this engine (spec max is 100). A provided (non-undefined) digit count outside that range raises a RangeError before any formatting.

Solutions

  1. Clamp digits to 0–100 before calling
  2. Use 0 or omit the argument for automatic minimum digits
  3. Switch to toPrecision if 1+ significant digits were intended

Example fix

// before
var s = n.toExponential(-1);
// after
var s = n.toExponential(Math.min(100, Math.max(0, d)));
Defensive patterns

Strategy: validation

Validate before calling

if (d != null && (d < 0 || d > 100)) throw new RangeError('fractionDigits must be 0..100');

Type guard

function isValidFractionDigits(d) { return d == null || (typeof d === 'number' && Number.isInteger(d) && d >= 0 && d <= 100); }

Try / catch

try { s = n.toExponential(d); } catch (e) { if (e instanceof RangeError) { s = n.toExponential(Math.min(100, Math.max(0, d))); } else { throw e; } }

Prevention

When it happens

Trigger: Calling n.toExponential(d) with d < 0 or d > 100, typically a computed or misremembered digit count; passing -1 intending 'auto'.

Common situations: Porting from toPrecision (whose floor is 1) or other engines; dynamically derived digit counts; typos like toExponential(-1).

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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsNumberPrototype.java:181

        if (args.length > 0 && args[0] instanceof java.math.BigInteger) {
            throw JsErrorException.typeError("Cannot convert a BigInt to a number");
        }
        boolean digitsAbsent = args.length == 0 || args[0] == Terms.UNDEFINED;
        int digits = digitsAbsent ? 0 : toIntegerArg(args[0], context);
        if (Double.isNaN(d)) return "NaN";
        if (d == Double.POSITIVE_INFINITY) return "Infinity";
        if (d == Double.NEGATIVE_INFINITY) return "-Infinity";
        if (d == 0.0) {
            // Spec §21.1.3.2: zero exponent always renders as "+0"; -0 strips its sign.
            if (digitsAbsent || digits == 0) return "0e+0";
            StringBuilder sb = new StringBuilder(digits + 5);
            sb.append("0.");
            for (int i = 0; i < digits; i++) sb.append('0');
            sb.append("e+0");
            return sb.toString();
        }
        if (!digitsAbsent && (digits < 0 || digits > 100)) {
            throw JsErrorException.rangeError("toExponential() fractionDigits must be between 0 and 100");
        }
        String formatted;
        if (digitsAbsent) {
            // Minimum-digits path: %.<n>e for the smallest n such that
            // round-tripping recovers d. For the common test262 cases this is
            // the same shape Double.toString produces, then we canonicalize.
            formatted = String.format(java.util.Locale.ROOT, "%.15e", d);
            // Trim trailing zeros from the mantissa fractional part.
            int e = formatted.indexOf('e');
            String mant = formatted.substring(0, e);
            String exp = formatted.substring(e);
            if (mant.contains(".")) {
                mant = mant.replaceAll("0+$", "");
                if (mant.endsWith(".")) mant = mant.substring(0, mant.length() - 1);
            }
            formatted = mant + exp;
        } else {
            formatted = String.format(java.util.Locale.ROOT, "%." + digits + "e", d);

View on GitHub (pinned to a22eb90246)