karatelabs/karate · error · JsErrorException

toPrecision() precision must be between 1 and 100

Error message

toPrecision() precision must be between 1 and 100

What it means

Number.prototype.toPrecision requires the precision argument to be within 1–100 (spec allows 1–2^53-1; this engine clamps to 100). Values outside the range are rejected with a RangeError before formatting proceeds.

Solutions

  1. Clamp or validate the precision to the 1–100 range before calling toPrecision
  2. Use toFixed(digits) if you intended fixed decimals and can accept its semantics
  3. Remove the argument entirely if you just want round-trip ToString behavior

Example fix

// before
var s = n.toPrecision(p); // p may be 0 or 150
// after
var p2 = Math.min(100, Math.max(1, p | 0));
var s = n.toPrecision(p2);
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isInteger(p) || p < 1 || p > 100) throw new RangeError('precision must be 1..100');

Type guard

function isValidPrecision(p) { return typeof p === 'number' && Number.isInteger(p) && p >= 1 && p <= 100; }

Try / catch

try { s = n.toPrecision(p); } catch (e) { if (e instanceof RangeError) { s = n.toPrecision(Math.min(100, Math.max(1, p))); } else { throw e; } }

Prevention

When it happens

Trigger: Calling n.toPrecision(p) where p is a Number less than 1 (including 0, negatives, NaN-like values that convert to 0) or greater than 100.

Common situations: Dynamically computed precision from user input or config; off-by-one code passing digit counts; porting code from engines with a wider allowed range.

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/6741dce92af47dfc. Report an issue: GitHub.

Appendix: source

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

        }
        return JsScalars.toFixed(d, digits);
    }

    private Object toPrecision(Context context, Object[] args) {
        double d = thisNumber(context).doubleValue();
        // Absent / undefined precision: spec returns ToString(x) — no range check.
        if (args.length == 0 || args[0] == Terms.UNDEFINED) {
            return Terms.numberToString(d);
        }
        if (args[0] instanceof java.math.BigInteger) {
            throw JsErrorException.typeError("Cannot convert a BigInt to a number");
        }
        int precision = 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 (precision < 1 || precision > 100) {
            throw JsErrorException.rangeError("toPrecision() precision must be between 1 and 100");
        }
        if (d == 0.0) {
            // Spec §21.1.3.4: zero uses fixed notation with (precision - 1) trailing zeros
            // after the decimal point. -0 stringifies as "0" (sign elided for the zero
            // mantissa per Number::toString §6.1.6.1.13).
            if (precision == 1) return "0";
            StringBuilder sb = new StringBuilder(precision + 2);
            sb.append("0.");
            for (int i = 1; i < precision; i++) sb.append('0');
            return sb.toString();
        }
        BigDecimal bd = new BigDecimal(d);
        bd = bd.round(new java.math.MathContext(precision, RoundingMode.HALF_UP));
        String result = bd.toString();
        // BigDecimal.toString uses scientific form for very large / small values; JS
        // switches between plain and exponential at |d| < 1e-6 or |d| >= 10^precision.
        if (result.contains("E") || result.contains("e")) {
            return result.replace('E', 'e');

View on GitHub (pinned to a22eb90246)