karatelabs/karate · error · JsErrorException
array index too large for dense storage:
Error message
array index too large for dense storage:
What it means
This RangeError guards the JsArray dense (ArrayList-backed) storage: assigning an index more than DENSE_PAD_LIMIT (10,000,000) beyond the current size would require padding millions of HOLE placeholders, risking JVM memory exhaustion. Karate throws instead of silently allocating, since true sparse storage is not implemented.
Solutions
- Use a small, contiguous index range (keep max index within 10M of current length)
- Use a plain JS object (or Java Map) as a sparse map instead of an array for large key spaces
- Restructure data so large indices are not needed (e.g. store {index: value} pairs)
Example fix
// before
var arr = []; arr[50000000] = 'x'; // RangeError
// after
var map = {}; map[50000000] = 'x'; Defensive patterns
Strategy: validation
Validate before calling
function safeDenseAssign(arr, i, v) { if (i - arr.length > 10000000) throw new Error('index too large'); arr[i] = v; } Type guard
function isWithinDenseLimit(arr, i) { return typeof i === 'number' && i >= 0 && i - arr.length <= 10000000; } Try / catch
try { arr[hugeIndex] = v; } catch (e) { if (String(e).indexOf('dense storage') !== -1) { sparse[hugeIndex] = v; } else { throw e; } } Prevention
- Never use raw large numbers (offsets, IDs, timestamps) as array indices
- Use objects/Maps for sparse key spaces
- Keep array indices contiguous and small
When it happens
Trigger: arr[hugeIndex] = value where hugeIndex exceeds arr.length + 10,000,000 (e.g. arr[99999999] = 1 on a small array); also reachable via defineOwn/defineOwnAccessor and applySet paths.
Common situations: Using large sparse indices expecting JS-like sparse-array semantics; generating IDs or offsets as array indices (e.g. byte offsets, timestamps used as indices).
Related errors
- Invalid array length
- Invalid array length
- Array.from requires an iterable or array-like object, not
- is not iterable
- Cannot assign to read only property 'length' of object…
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/677c265b0d8db210.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsArray.java:216
* inspection paths that need slot identity. */
PropertySlot getOwnSlot(String name) {
return namedProps == null ? null : namedProps.get(name);
}
/** Spec CanonicalNumericIndexString check (§7.1.21 narrowed to integers).
* Returns the integer value if {@code s} is a canonical integer-index
* string ("0", "1", "42"), or {@code -1} otherwise. Package-private so
* {@link JsObject#orderedOwnKeys} can apply §9.1.11.1 ordering. */
/** Largest hole-pad a single write may create. A sparse write like
* {@code arr[2**30] = x} used to append a billion HOLEs and die with a
* raw OutOfMemoryError; past this bound the write is refused with a JS
* RangeError instead — loud, catchable, and it cannot take the JVM
* down. True sparse storage is the deferred HOLE-elimination rework. */
static final int DENSE_PAD_LIMIT = 10_000_000;
void checkDensePad(long index) {
if (index - list.size() > DENSE_PAD_LIMIT) {
throw JsErrorException.rangeError(
"array index too large for dense storage: " + index);
}
}
static int parseIndex(String s) {
// Strict canonical-integer parse: rejects "01", "+1", "-1", "1.0".
// Spec: an array index is a String whose value is a CanonicalNumericIndexString
// less than 2^32 - 1. The dense store is bounded by int, so indices
// beyond Integer.MAX_VALUE are treated as ordinary named properties —
// the long accumulator keeps a 10-digit index like "4294967294" from
// silently overflowing int into a negative value that a raw
// list.get() then crashes on (it used to surface as
// "Index -2 out of bounds", a Java leak).
int n = s.length();
if (n == 0) return -1;
if (n > 10) return -1; // any 11+ digit index exceeds 2^32-1 and isn't an array index
long v = 0;
for (int i = 0; i < n; i++) {View on GitHub (pinned to a22eb90246)