apache/beam · error · IndexOutOfBoundsException
Position was out of bounds for ranges .
Error message
Position %s was out of bounds for ranges %s.
What it means
PCollectionViews.computePositionForIndex maps a global list index onto the materialized iterable view's offset ranges. A negative index (or one not covered by any range, surfacing later) throws IndexOutOfBoundsException 'Position %s was out of bounds for ranges %s.' This is a defensive bounds check used in testing the iterable-view position computation; it should be unreachable through normal pipeline use and indicates an out-of-range lookup.
Solutions
- Clamp/validate the index before calling computePositionForIndex: only pass indices within [0, totalElements).
- If hit through view access, verify the iterable view materialization ranges match the data (re-run with matching SDK/runner versions).
- For tests, compute the expected index from the same OffsetRange map rather than hardcoding it.
- Report to Beam if a legitimate in-range index triggers this via View.asList() access — likely a runner bug.
Example fix
// before
KV<Long, Integer> pos = PCollectionViews.computePositionForIndex(ranges, index);
// after
if (index < 0 || index >= totalElements) throw new IllegalArgumentException("index " + index + " out of range");
KV<Long, Integer> pos = PCollectionViews.computePositionForIndex(ranges, index); Defensive patterns
Strategy: validation
Validate before calling
if (index < 0 || index >= totalElements) {
throw new IllegalArgumentException("index out of range: " + index);
}
KV<Long, Integer> pos = PCollectionViews.computePositionForIndex(ranges, index); Try / catch
try {
KV<Long, Integer> pos = PCollectionViews.computePositionForIndex(ranges, index);
} catch (IndexOutOfBoundsException e) {
/* clamp index or recompute ranges */
} Prevention
- Only pass indices derived from the same range map, never hand-computed constants.
- Keep runner and SDK versions aligned so iterable-view metadata matches access patterns.
- In tests, assert index bounds before invoking this VisibleForTesting helper.
When it happens
Trigger: Calling computePositionForIndex (a @VisibleForTesting static helper) with a negative index, or via iterable view materialization paths where an index lookup falls outside all OffsetRange buckets of the view.
Common situations: Unit tests exercising PCollectionViews iterable-view internals with hand-computed indices; runner-side iterable-view random-access where the materialization ranges and the requested index disagree (runner/SDK mismatch or corrupted view metadata).
Related errors
- No field at index
- Unable to find value #
- A function must be provided to convert the input type into…
- A PValue contained in
- A schema was provided without a data format (or viceversa)…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/2b616bfa725c701b.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/values/PCollectionViews.java:991
@VisibleForTesting
static int computeTotalNumElements(
Map<OffsetRange, Integer> nonOverlappingRangesToNumElementsPerPosition) {
long sum = 0;
for (Map.Entry<OffsetRange, Integer> range :
nonOverlappingRangesToNumElementsPerPosition.entrySet()) {
sum +=
Math.multiplyExact(
Math.subtractExact(range.getKey().getTo(), range.getKey().getFrom()),
range.getValue());
}
return Ints.checkedCast(sum);
}
@VisibleForTesting
static KV<Long, Integer> computePositionForIndex(
Map<OffsetRange, Integer> nonOverlappingRangesToNumElementsPerPosition, int index) {
if (index < 0) {
throw new IndexOutOfBoundsException(
String.format(
"Position %s was out of bounds for ranges %s.",
index, nonOverlappingRangesToNumElementsPerPosition));
}
for (Map.Entry<OffsetRange, Integer> range :
nonOverlappingRangesToNumElementsPerPosition.entrySet()) {
int numElementsInRange =
Ints.checkedCast(
Math.multiplyExact(
Math.subtractExact(range.getKey().getTo(), range.getKey().getFrom()),
range.getValue()));
if (numElementsInRange <= index) {
index -= numElementsInRange;
continue;
}
long position = range.getKey().getFrom() + index / range.getValue();
int subPosition = index % range.getValue();
return KV.of(position, subPosition);View on GitHub (pinned to 12126d8942)