prestodb/presto · error · IllegalArgumentException

positionCount is negative

Error message

positionCount is negative

What it means

A block cannot have a negative number of positions. The Int128ArrayBlock constructor validates positionCount >= 0 and throws IllegalArgumentException if it is negative, since all downstream reads iterate that many positions.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlock.java:69

    @Nullable
    private final boolean[] valueIsNull;
    private final long[] values;

    private final long retainedSizeInBytes;

    public Int128ArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, long[] values)
    {
        this(0, positionCount, valueIsNull.orElse(null), values);
    }

    Int128ArrayBlock(int positionOffset, int positionCount, boolean[] valueIsNull, long[] values)
    {
        if (positionOffset < 0) {
            throw new IllegalArgumentException("positionOffset is negative");
        }
        this.positionOffset = positionOffset;
        if (positionCount < 0) {
            throw new IllegalArgumentException("positionCount is negative");
        }
        this.positionCount = positionCount;

        if (values.length - (positionOffset * 2) < positionCount * 2) {
            throw new IllegalArgumentException("values length is less than positionCount");
        }
        this.values = values;

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

        retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);
    }

    @Override
    public long getSizeInBytes()

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Clamp the computed count: int count = Math.max(0, end - start).
  2. Assert end >= start before constructing the block so the real bug (wrong range order) surfaces at the source.
  3. If the count came from serialized data, validate it against the remaining buffer size before use.

Example fix

// before
Int128ArrayBlock block = new Int128ArrayBlock(0, end - start, isNull, values);
// after
checkArgument(end >= start, "invalid range [%s, %s)", start, end);
Int128ArrayBlock block = new Int128ArrayBlock(0, end - start, isNull, values);
Defensive patterns

Strategy: validation

Validate before calling

checkArgument(end >= start, "invalid range [%s, %s): positionCount would be negative", start, end);
int positionCount = end - start;

Type guard

boolean validPositionCount(int positionCount) { return positionCount >= 0; }

Try / catch

try {
    block = new Int128ArrayBlock(0, positionCount, isNull, values);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("positionCount is negative")) {
        throw new IllegalStateException("range computation gave negative count " + positionCount, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Constructing Int128ArrayBlock with a negative positionCount, usually from a subtraction like endPosition - startPosition where end < start, or an uninitialized count variable.

Common situations: Page splitting/merging code where range arithmetic went backwards; off-by-one fixes that inverted a subtraction; deserializers reading a corrupt negative count from a serialized page.

Related errors


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