prestodb/presto · error · IllegalArgumentException
position is not valid
Error message
position is not valid
What it means
checkReadablePosition guards every position-based read on Int128ArrayBlockBuilder (getLong, isNull, writePositionTo, getSingleValueBlock, copyPositions). Any position outside [0, getPositionCount()) is rejected with IllegalArgumentException because the builder has no value at that index.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlockBuilder.java:439
return new Int128ArrayBlock(0, length, newValueIsNull, newValues);
}
@Override
public String getEncodingName()
{
return Int128ArrayBlockEncoding.NAME;
}
@Override
public String toString()
{
return format("Int128ArrayBlockBuilder(%d){positionCount=%d}", hashCode(), getPositionCount());
}
private void checkReadablePosition(int position)
{
if (position < 0 || position >= getPositionCount()) {
throw new IllegalArgumentException("position is not valid");
}
}
@Override
public long getLongUnchecked(int internalPosition, int offset)
{
assert internalPositionInRange(internalPosition, getOffsetBase(), getPositionCount());
assert offset == 0 || offset == 8 : "offset must be 0 or 8";
return values[internalPosition * 2 + bitCount(offset)];
}
@Override
public boolean isNullUnchecked(int internalPosition)
{
assert mayHaveNull() : "no nulls present";
assert internalPositionInRange(internalPosition, getOffsetBase(), getPositionCount());
return valueIsNull[internalPosition];
}View on GitHub (pinned to 55bb57d202)
Solutions
- Clamp/validate the loop bound: iterate i < block.getPositionCount().
- Only read after entries are closed (closeEntry) so positionCount reflects written values.
- Re-fetch positions from the current block instance instead of caching indexes across rebuilds.
Example fix
// before
for (int i = 0; i <= block.getPositionCount(); i++) { block.isNull(i); }
// after
for (int i = 0; i < block.getPositionCount(); i++) { block.isNull(i); } Defensive patterns
Strategy: validation
Validate before calling
if (position < 0 || position >= block.getPositionCount()) {
throw new IllegalArgumentException("position out of range: " + position);
} Type guard
boolean readablePosition(Block b, int position) {
return position >= 0 && position < b.getPositionCount();
} Try / catch
try {
value = builder.getLong(position, offset);
} catch (IllegalArgumentException e) {
log.warn("Bad position {} on builder with {} positions", position, builder.getPositionCount());
return null;
} Prevention
- Iterate with i < getPositionCount(), never <=
- Close all entries before reading back from a builder
- Do not cache position indexes across block rebuilds or page restarts
When it happens
Trigger: Reading at a position equal to or greater than positionCount — commonly position == positionCount when iterating with <=, reading after an unfinished entry, or using stale indexes after the builder grew/reset.
Common situations: Off-by-one loops over block positions; reading a builder before closeEntry/finalization changed positionCount; reusing cached position indexes after block rebuild or page operator restarts.
Related errors
- position is not valid
- position is not valid
- position is not valid: " + position
- position is not valid: " + position
- otherOffset %d, length %d are invalid for otherSlice with le
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/8e84dad07ba40526.
Report an issue: GitHub.