prestodb/presto · error · IllegalArgumentException

position is not valid

Error message

position is not valid

What it means

AbstractRowBlock.checkReadablePosition validates that a position argument is within [0, positionCount). Any reader API (copyPositions, getBlock, writePositionTo, getSingleValueBlock, getEstimatedDataSizeForStats) called with an out-of-range position throws IllegalArgumentException with the generic message "position is not valid".

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/AbstractRowBlock.java:382

        Block[] rawFieldBlocks = getRawFieldBlocks();
        long size = 0;
        for (int i = 0; i < numFields; i++) {
            size += rawFieldBlocks[i].getEstimatedDataSizeForStats(getFieldBlockOffset(position));
        }
        return size;
    }

    @Override
    public boolean mayHaveNull()
    {
        return getRowIsNull() != null;
    }

    protected final void checkReadablePosition(int position)
    {
        if (position < 0 || position >= getPositionCount()) {
            throw new IllegalArgumentException("position is not valid");
        }
    }

    @Override
    public Block getBlockUnchecked(int internalPosition)
    {
        assert internalPositionInRange(internalPosition, getOffsetBase(), getPositionCount());
        return new SingleRowBlock(getFieldBlockOffsets()[internalPosition], getRawFieldBlocks());
    }

    @Override
    public boolean isNullUnchecked(int internalPosition)
    {
        assert mayHaveNull() : "no nulls present";
        assert internalPositionInRange(internalPosition, getOffsetBase(), getPositionCount());
        return getRowIsNull()[internalPosition];
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Clamp/bound loop indices with block.getPositionCount() before calling reader methods.
  2. Verify the position source: only pass positions produced for this same block, not stale or foreign indices.
  3. Use block iterator or getPositions/processing APIs that enforce bounds automatically.
  4. Reproduce with the caller stack trace and fix the off-by-one in the operator rather than catching the exception.

Example fix

// before
for (int i = 0; i <= block.getPositionCount(); i++) {
    block.writePositionTo(i, output);
}
// after
for (int i = 0; i < block.getPositionCount(); i++) {
    block.writePositionTo(i, output);
}
Defensive patterns

Strategy: type-guard

Validate before calling

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

Type guard

static boolean hasReadablePosition(Block block, int position) {
    return block != null && position >= 0 && position < block.getPositionCount();
}

Try / catch

try {
    block.writePositionTo(position, output);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().equals("position is not valid")) {
        throw new IndexOutOfBoundsException("position " + position + " out of range for block of " + block.getPositionCount());
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling any of those public reader methods with a negative position, or a position >= the block's position count; commonly from iterating past the end or using positions from a different block.

Common situations: Off-by-one loops in custom operators/expression implementations; using an internal position where an external one is expected; null-handling bugs that skip a position decrement.

Related errors


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