prestodb/presto · error · IllegalArgumentException

position is not valid

Error message

position is not valid

What it means

ByteArrayBlockBuilder.checkReadablePosition throws IllegalArgumentException when a position argument is negative or >= getPositionCount() of the builder's currently built region. It guards the same read APIs as ByteArrayBlock (getByte, isNull, writePositionTo, getSingleValueBlock, copyPositions) while the values still live in the builder.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/ByteArrayBlockBuilder.java:328

        return new ByteArrayBlock(0, length, newValueIsNull, newValues);
    }

    @Override
    public String getEncodingName()
    {
        return ByteArrayBlockEncoding.NAME;
    }

    @Override
    public String toString()
    {
        return format("ByteArrayBlockBuilder(%d){positionCount=%d}", hashCode(), getPositionCount());
    }

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

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

    @Override
    public byte getByteUnchecked(int internalPosition)
    {
        assert internalPositionInRange(internalPosition, getOffsetBase(), getPositionCount());
        return values[internalPosition];
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Call builder.getPositionCount() and bound all reads to it, reading positions 0..positionCount-1
  2. Ensure closeEntry() is invoked after writing each value so appended values become readable positions
  3. Use build() to convert to a Block before random-position reads if the region semantics are unclear
  4. Validate incoming position arrays before calling copyPositions on a builder

Example fix

// before
builder.writeByte(7); int v = builder.getByte(builder.getPositionCount()); // throws
// after
builder.writeByte(7); builder.closeEntry(); int v = builder.getByte(builder.getPositionCount() - 1);
Defensive patterns

Strategy: validation

Validate before calling

int count = builder.getPositionCount();
if (position < 0 || position >= count) {
    throw new IllegalArgumentException("position " + position + " out of range [0, " + count + ")");
}
byte v = builder.getByte(position);

Type guard

boolean builderHasPosition(ByteArrayBlockBuilder builder, int position) {
    return position >= 0 && position < builder.getPositionCount();
}

Try / catch

try {
    byte v = builder.getByte(position);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("builder position out of range; call closeEntry()/build() before reading", e);
}

Prevention

When it happens

Trigger: Reading from a ByteArrayBlockBuilder with position >= getPositionCount(), e.g. calling getByte(positionCount) before build() flushes the last value; forgetting that appended-but-not-finished values may not count; using positions from a differently sized block; negative positions from unvalidated input.

Common situations: Custom aggregation/accumulator code reading builder positions before closing the entry (missing builder.closeEntry()); copying data between blocks whose position counts differ; testing code assuming unread appended values are immediately visible.

Related errors


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