karatelabs/karate · error · JsErrorException

Invalid array length

Error message

Invalid array length

What it means

This RangeError is thrown by Karate's JS engine when an array-like operation would produce a result length at or above the JVM-safe bound (spec ArrayCreate throws above 2^32-1; this store bound is lower and documented in TEST262.md). It exists so a lying {length: 2**32} array-like cannot OOM the JVM through map / splice / toReversed / toSorted / toSpliced.

Solutions

  1. Fix the receiver's length value to a realistic array size
  2. Ensure inputs to map/splice/toSorted etc. are real arrays, not array-likes with huge lengths
  3. Wrap the call in try/catch and treat RangeError as invalid input
  4. Validate length <= 2^32-2 before invoking array methods on array-likes

Example fix

// before
var fake = { length: 4294967295 };
Array.prototype.map.call(fake, f);
// after
var fake = { length: 4294967295 };
if (fake.length > 2147483646) throw new Error('array-like too large');
Array.prototype.map.call(fake, f);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof obj.length !== 'number' || obj.length < 0 || obj.length > 2147483646) throw new Error('array-like length out of safe range: ' + obj.length);

Type guard

function isSafeArrayLike(o) { return o != null && typeof o.length === 'number' && Number.isInteger(o.length) && o.length >= 0 && o.length <= 2147483646; }

Prevention

When it happens

Trigger: Calling len, removed, result, items, or the newLen path of array methods on a receiver whose length coerces to Integer.MAX_VALUE (2147483647), e.g. an object with {length: 4294967295} passed to Array.prototype.map.call, or a huge new length passed to splice/unshift.

Common situations: Hand-rolled array-like objects with inflated length fields; JSON payloads with spoofed length; ported JS that relies on V8's larger limits; fuzzing or hostile scripts evaluated in Karate's embedded JS.

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/9ffd252d85defb76. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsArrayPrototype.java:422

        Number n = lenObj instanceof ObjectLike
                ? Terms.toNumberCoerce(lenObj, ctx)
                : Terms.objectToNumber(lenObj);
        if (ctx != null && ctx.isError()) return 0;
        double d = n == null ? Double.NaN : n.doubleValue();
        if (Double.isNaN(d) || d <= 0) return 0;
        if (d >= Integer.MAX_VALUE) return Integer.MAX_VALUE;
        return (int) d;
    }

    /** {@link #lengthOf} clamps a huge claimed length to Integer.MAX_VALUE;
     *  a result of that magnitude cannot be dense-allocated. The spec answer
     *  is RangeError (ArrayCreate §10.4.2.2 throws above 2^32-1; the store
     *  bound here is lower and documented in TEST262.md) — throwing it here
     *  keeps a lying {@code {length: 2**32}} array-like from OOMing the JVM
     *  through map / splice / toReversed / toSorted / toSpliced. */
    private static int checkResultLength(int len) {
        if (len == Integer.MAX_VALUE) {
            throw JsErrorException.rangeError("Invalid array length");
        }
        return len;
    }

    /** Spec §23.1.3.34 step 4 (unshift) / §23.1.3.31 (splice): a receiver
     *  whose length plus the inserted count would exceed 2^53-1 throws
     *  TypeError before any element is moved. Reads the raw double length —
     *  {@link #lengthOf}'s int clamp cannot see these magnitudes. */
    private static void checkLengthLimit(ObjectLike target, CoreContext ctx, int addCount) {
        Object lenObj = target.getMember("length", target, ctx);
        if (lenObj == null || lenObj == Terms.UNDEFINED) return;
        Number n = lenObj instanceof ObjectLike
                ? Terms.toNumberCoerce(lenObj, ctx)
                : Terms.objectToNumber(lenObj);
        if (ctx != null && ctx.isError()) return;
        double d = n == null ? Double.NaN : n.doubleValue();
        if (d + addCount > 9007199254740991.0) { // 2^53 - 1
            throw JsErrorException.typeError("Invalid array length");

View on GitHub (pinned to a22eb90246)