prestodb/presto · error · IllegalArgumentException
positionCount is negative
Error message
positionCount is negative
What it means
ShortArrayBlock's constructor validates its arguments before storing them. positionCount represents the number of entries in the block, and a negative count is meaningless, so the constructor throws IllegalArgumentException immediately rather than creating a corrupt block. This is a fail-fast guard against bad block construction.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/ShortArrayBlock.java:61
@Nullable
private final boolean[] valueIsNull;
private final short[] values;
private final long retainedSizeInBytes;
public ShortArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, short[] values)
{
this(0, positionCount, valueIsNull.orElse(null), values);
}
ShortArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, short[] values)
{
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 (values.length - arrayOffset < positionCount) {
throw new IllegalArgumentException("values length is less than positionCount");
}
this.values = values;
if (valueIsNull != null && valueIsNull.length - arrayOffset < 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
- Check the caller's positionCount computation for swapped or underflowing arithmetic (e.g. end - start with end < start).
- Clamp or validate the value before constructing: if (positionCount < 0) throw ... or use Math.max(0, positionCount).
- Verify the data source (e.g. deserialized length field) is not corrupted; re-serialize the input.
Example fix
// before int count = end - start; Block block = new ShortArrayBlock(0, count, new short[8], null); // after int count = Math.max(0, end - start); checkArgument(end >= start, "end before start"); Block block = new ShortArrayBlock(0, count, new short[8], null);
Defensive patterns
Strategy: validation
Validate before calling
if (positionCount < 0) {
throw new IllegalArgumentException("positionCount must be >= 0, got " + positionCount);
} Type guard
boolean isValidBlockShape(int arrayOffset, int positionCount, short[] values) {
return arrayOffset >= 0 && positionCount >= 0 && values.length - arrayOffset >= positionCount;
} Try / catch
try {
Block block = new ShortArrayBlock(arrayOffset, positionCount, values, valueIsNull);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("positionCount is negative")) {
positionCount = Math.max(0, positionCount); // or log and rethrow with context
} else {
throw e;
}
} Prevention
- Compute positionCount as end - start and assert end >= start before constructing.
- Use Math.max(0, n) when deriving counts from possibly-underflowing arithmetic.
- Unit-test block construction with boundary values (0, -1, Integer.MAX_VALUE).
When it happens
Trigger: Calling ShortArrayBlock's constructor (directly or via factory methods like ShortArrayBlock.fromShortArray) with a negative positionCount argument.
Common situations: Custom block building code that computes positionCount via subtraction (e.g. end - start on swapped indices), off-by-one bugs in aggregation/partitioning code, or deserialization feeding a corrupted/underflowed int.
Related errors
- Offset is not monotonically ascending. offsets[%s]=%s, offse
- A null map must have zero entries
- Number of fields in RowBlock must be positive
- position is not valid
- position is not valid
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/31eacb007c4c64f7.
Report an issue: GitHub.