prestodb/presto · error · IllegalArgumentException

positionCount is negative

Error message

positionCount is negative

What it means

A RunLengthEncodedBlock's positionCount states how many times the single value repeats; a negative count is meaningless and would break downstream bounds checks, so the constructor validates it with IllegalArgumentException.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/RunLengthEncodedBlock.java:66

    private final Block value;
    private final int positionCount;

    public RunLengthEncodedBlock(Block value, int positionCount)
    {
        requireNonNull(value, "value is null");
        if (value.getPositionCount() != 1) {
            throw new IllegalArgumentException(format("Expected value to contain a single position but has %s positions", value.getPositionCount()));
        }

        if (value instanceof RunLengthEncodedBlock) {
            this.value = ((RunLengthEncodedBlock) value).getValue();
        }
        else {
            this.value = value;
        }

        if (positionCount < 0) {
            throw new IllegalArgumentException("positionCount is negative");
        }

        this.positionCount = positionCount;
    }

    public Block getValue()
    {
        return value;
    }

    @Override
    public int getPositionCount()
    {
        return positionCount;
    }

    @Override
    public long getSizeInBytes()

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Validate positionCount >= 0 before constructing (clamp to 0 if an empty range is legal)
  2. Fix the subtraction/loop bounds that produced the negative value
  3. Use Math.max(0, end - start) when computing counts from ranges

Example fix

// before
int count = end - start; // may be negative
return new RunLengthEncodedBlock(value, count);
// after
int count = Math.max(0, end - start);
return new RunLengthEncodedBlock(value, count);
Defensive patterns

Strategy: validation

Validate before calling

// before constructing an RLE block
if (positionCount < 0) {
    positionCount = 0; // or throw with context about the computation
}
RunLengthEncodedBlock rle = new RunLengthEncodedBlock(value, positionCount);

Try / catch

try {
    return new RunLengthEncodedBlock(value, count);
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("positionCount is negative")) {
        throw new IllegalStateException("negative RLE count from range computation [" + start + ", " + end + ")", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing a negative integer as the second argument to new RunLengthEncodedBlock(value, positionCount), typically from an unchecked subtraction (e.g. rangeEnd - rangeStart) or an uninitialized variable.

Common situations: Computing retained positions during block compaction where start > end produces a negative delta; operator code computing 'remaining' positions that underflows.

Related errors


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