prestodb/presto · error · IllegalArgumentException

positionCount is negative

Error message

positionCount is negative

What it means

VariableWidthBlock's constructor rejects a negative positionCount. A block cannot represent a negative number of positions; passing one indicates an arithmetic bug (e.g. end - start with end < start) in the calling code.

Source

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

    @Nullable
    private final boolean[] valueIsNull;

    private final long retainedSizeInBytes;
    private final long sizeInBytes;

    public VariableWidthBlock(int positionCount, Slice slice, int[] offsets, Optional<boolean[]> valueIsNull)
    {
        this(0, positionCount, slice, offsets, valueIsNull.orElse(null));
    }

    VariableWidthBlock(int arrayOffset, int positionCount, Slice slice, int[] offsets, boolean[] valueIsNull)
    {
        if (arrayOffset < 0) {
            throw new IllegalArgumentException("arrayOffset is negative");
        }
        this.arrayOffset = arrayOffset;
        if (positionCount < 0) {
            throw new IllegalArgumentException("positionCount is negative");
        }
        this.positionCount = positionCount;

        if (slice == null) {
            throw new IllegalArgumentException("slice is null");
        }
        this.slice = slice;

        if (offsets.length - arrayOffset < (positionCount + 1)) {
            throw new IllegalArgumentException("offsets length is less than positionCount");
        }
        this.offsets = offsets;

        if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
            throw new IllegalArgumentException("valueIsNull length is less than positionCount");
        }
        this.valueIsNull = valueIsNull;

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Fix the computation so positionCount = end - start is never negative (check argument order).
  2. Return an empty block (positionCount 0) for empty ranges instead of computing a negative count.
  3. Validate range parameters before constructing the block.

Example fix

// before
int count = start - end; // inverted
new VariableWidthBlock(0, count, slice, offsets, null);
// after
int count = Math.max(0, end - start);
new VariableWidthBlock(0, count, slice, offsets, null);
Defensive patterns

Strategy: validation

Validate before calling

int positionCount = end - start;
checkState(positionCount >= 0, "inverted range: start=%s end=%s", start, end);

Try / catch

try {
    new VariableWidthBlock(0, positionCount, slice, offsets, valueIsNull);
} catch (IllegalArgumentException e) {
    // fall back to empty block and log the bad range
}

Prevention

When it happens

Trigger: Constructing VariableWidthBlock where positionCount < 0, commonly from computing count as an end position minus start position where the range is inverted or empty ranges are mis-handled as negative.

Common situations: Range slicing code with swapped start/end arguments; aggregation that subtracts lengths without guarding empty selections.

Related errors


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