prestodb/presto · error · IllegalArgumentException
offsets length is less than positionCount
Error message
offsets length is less than positionCount
What it means
The offsets array must contain positionCount + 1 entries starting at arrayOffset (offsets[i] and offsets[i+1] delimit each value). If offsets.length - arrayOffset < positionCount + 1 there are not enough boundary entries to decode every position, so the constructor throws IllegalArgumentException.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/VariableWidthBlock.java:85
VariableWidthBlock(int arrayOffset, int positionCount, Slice slice, int[] offsets, boolean[] valueIsNull)
{
if (arrayOffset < 0) {
throw new IllegalArgumentException("arrayOffset is negative");
}
this.arrayOffset = arrayOffset;
if (positionCount < 0) {
throw new IllegalArgumentException("positionCount is negative");
}
this.positionCount = positionCount;
if (slice == null) {
throw new IllegalArgumentException("slice is null");
}
this.slice = slice;
if (offsets.length - arrayOffset < (positionCount + 1)) {
throw new IllegalArgumentException("offsets length is less than positionCount");
}
this.offsets = offsets;
if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("valueIsNull length is less than positionCount");
}
this.valueIsNull = valueIsNull;
sizeInBytes = offsets[arrayOffset + positionCount] - offsets[arrayOffset] + ((Integer.BYTES + Byte.BYTES) * (long) positionCount);
retainedSizeInBytes = INSTANCE_SIZE + slice.getRetainedSize() + sizeOf(valueIsNull) + sizeOf(offsets);
}
@Override
public final int getPositionOffset(int position)
{
return offsets[position + arrayOffset];
}
View on GitHub (pinned to 55bb57d202)
Solutions
- Ensure offsets has at least arrayOffset + positionCount + 1 entries (include the trailing sentinel).
- Verify positionCount matches the offsets array actually passed, not a different block's.
- Check the serialization/read path for truncation producing short offsets arrays.
Example fix
// before int[] offsets = new int[positions.length]; // missing trailing entry new VariableWidthBlock(0, positions.length, slice, offsets, null); // after int[] offsets = new int[positions.length + 1]; // +1 sentinel new VariableWidthBlock(0, positions.length, slice, offsets, null);
Defensive patterns
Strategy: validation
Validate before calling
checkState(offsets.length - arrayOffset >= positionCount + 1,
"offsets too short: need %s, have %s", positionCount + 1 + arrayOffset, offsets.length); Try / catch
try {
new VariableWidthBlock(arrayOffset, positionCount, slice, offsets, valueIsNull);
} catch (IllegalArgumentException e) {
// inspect page truncation / mismatched offsets source
} Prevention
- Always include the trailing sentinel entry in offsets arrays
- Keep offsets and positionCount derived from the same page read
- Detect truncated serialized pages before block construction
When it happens
Trigger: Constructing VariableWidthBlock with an offsets array shorter than arrayOffset + positionCount + 1; typical when positionCount was computed from data length but offsets came from a truncated or differently-sized page.
Common situations: Corrupt/truncated serialized pages; mixing offsets arrays between blocks with different position counts; off-by-one when building offsets manually (forgetting the final sentinel entry).
Related errors
- Offset is not monotonically ascending. offsets[%s]=%s, offse
- A null map must have zero entries
- Number of fields in RowBlock must be positive
- position is not valid
- position is not valid
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/05d1d499769a89a2.
Report an issue: GitHub.