prestodb/presto · error · IllegalArgumentException

Invalid position %s in block with %s positions

Error message

Invalid position %s in block with %s positions

What it means

BlockUtil.checkValidPosition validates a single position index against a block's positionCount, throwing IllegalArgumentException if position is negative or >= positionCount. It protects single-position accessors (isNull, getLong, getSlice, etc.) from reading out of bounds.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/BlockUtil.java:75

    static void checkValidRegion(int positionCount, int positionOffset, int length)
    {
        if (positionOffset < 0 || length < 0 || positionOffset + length > positionCount) {
            throw new IndexOutOfBoundsException(format("Invalid position %s and length %s in block with %s positions", positionOffset, length, positionCount));
        }
    }

    static void checkValidPositions(boolean[] positions, int positionCount)
    {
        if (positions.length != positionCount) {
            throw new IllegalArgumentException(format("Invalid positions array size %d, actual position count is %d", positions.length, positionCount));
        }
    }

    static void checkValidPosition(int position, int positionCount)
    {
        if (position < 0 || position >= positionCount) {
            throw new IllegalArgumentException(format("Invalid position %s in block with %s positions", position, positionCount));
        }
    }

    static void checkValidSliceRange(int sourceIndex, int length)
    {
        //sourceIndex + length can overflow integer range
        if (sourceIndex > MAX_ARRAY_SIZE - length) {
            throw new SliceTooLargeException(format("Cannot allocate slice larger than %d bytes", MAX_ARRAY_SIZE));
        }
    }

    static int calculateNewArraySize(int currentSize)
    {
        // grow array by 50%
        long newSize = (long) currentSize + (currentSize >> 1);

        // verify new size is within reasonable bounds
        if (newSize < DEFAULT_CAPACITY) {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Verify 0 <= position < block.getPositionCount() before accessing positions
  2. Ensure the position index belongs to the same block/page that produced it (don't reuse indices across pages)
  3. Catch IllegalArgumentException at the accessor boundary and log position and positionCount

Example fix

// before
if (position <= block.getPositionCount()) {
    value = block.getLong(position);
}
// after
if (position >= 0 && position < block.getPositionCount()) {
    value = block.getLong(position);
}
Defensive patterns

Strategy: type-guard

Validate before calling

checkArgument(position >= 0 && position < block.getPositionCount(), "position %s out of [0,%s)", position, block.getPositionCount());

Type guard

boolean isValidPosition(Block block, int position) {
    return position >= 0 && position < block.getPositionCount();
}

Try / catch

try {
    long v = block.getLong(position);
} catch (IllegalArgumentException e) {
    throw new PrestoException(GENERIC_INTERNAL_ERROR, "position " + position + " invalid for block of " + block.getPositionCount(), e);
}

Prevention

When it happens

Trigger: Calling block.isNull(pos)/getLong(pos)/getSlice(pos) with a position from a stale row index, from a page that was already consumed/compacted, or from iterating with wrong bounds (e.g. < positionCount+1).

Common situations: Operator loops using an off-by-one upper bound; row-number references into blocks that have since been compacted; mixing positions between blocks in a page with differing position counts.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/5049270d81761dfd. Report an issue: GitHub.