prestodb/presto · error · IllegalArgumentException
position is not valid
Error message
position is not valid
What it means
checkReadablePosition guards every public position-accessing method of Int128ArrayBlock (getLong, isNull, writePositionTo, getSingleValueBlock, copyPositions). Any position outside [0, getPositionCount()) is invalid because the block only exposes its visible position range; IllegalArgumentException is thrown rather than reading out of bounds.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlock.java:337
return new Int128ArrayBlock(0, length, newValueIsNull, newValues);
}
@Override
public String getEncodingName()
{
return Int128ArrayBlockEncoding.NAME;
}
@Override
public String toString()
{
return format("Int128ArrayBlock(%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 int getOffsetBase()
{
return positionOffset;
}
@OverrideView on GitHub (pinned to 55bb57d202)
Solutions
- Clamp/bound loops with the block's own getPositionCount(): for (int i = 0; i < block.getPositionCount(); i++).
- Translate parent-block positions to region-relative positions before calling accessors on a region view.
- Check position bounds explicitly before access when the position comes from external input (e.g. join probes, output channel indices).
Example fix
// before
for (int i = 0; i <= region.getPositionCount(); i++) { region.isNull(i); } // off-by-one
// after
for (int i = 0; i < region.getPositionCount(); i++) { region.isNull(i); } Defensive patterns
Strategy: type-guard
Validate before calling
if (position < 0 || position >= block.getPositionCount()) {
throw new IllegalArgumentException("position " + position + " out of range for block with " + block.getPositionCount() + " positions");
} Type guard
boolean isReadablePosition(Block block, int position) {
return position >= 0 && position < block.getPositionCount();
} Try / catch
try {
value = block.getLong(position, 0);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("position is not valid")) {
throw new IllegalStateException("stale position " + position + " for block count " + block.getPositionCount(), e);
}
throw e;
} Prevention
- Bound all loops with the block's own getPositionCount(), never a cached count.
- Convert parent positions to region-relative positions after getRegion/getPositionRange.
- Reuse position indexes only within the same page; revalidate across pages.
When it happens
Trigger: Calling any accessor with position < 0 or position >= getPositionCount(); iterating with a stale position count after the block was replaced by a region/getRegion view with fewer positions; using an absolute source position on a sliced block instead of a relative one.
Common situations: Operators caching a position index across page boundaries; using the parent block's positions on a getRegion result; off-by-one loops written as i <= positionCount; reusing positions from a previous page whose count was larger.
Related errors
- position is not valid
- position is not valid
- position is not valid
- position is not valid: " + position
- position is not valid: " + position
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/e517a86818ff825f.
Report an issue: GitHub.