prestodb/presto · error · IllegalArgumentException
isNull length is less than positionCount
Error message
isNull length is less than positionCount
What it means
The optional null bitmap must cover every position the block exposes: valueIsNull.length - positionOffset must be >= positionCount. The constructor throws IllegalArgumentException when the isNull array is shorter than the visible position range.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlock.java:79
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()
{
return SIZE_IN_BYTES_PER_POSITION * (long) positionCount;
}
@Override
public OptionalInt fixedSizeInBytesPerPosition()
{
return OptionalInt.of(SIZE_IN_BYTES_PER_POSITION);
}
View on GitHub (pinned to 55bb57d202)
Solutions
- Size valueIsNull as positionOffset + positionCount booleans, matching the values array's position coverage.
- When creating a region, slice valueIsNull with the same offset logic used for positions (Arrays.copyOfRange(valueIsNull, offset, offset + count)).
- Validate column-array lengths are equal before constructing the block.
Example fix
// before boolean[] valueIsNull = new boolean[positionCount]; // ignores positionOffset // after boolean[] valueIsNull = new boolean[positionOffset + positionCount];
Defensive patterns
Strategy: validation
Validate before calling
if (valueIsNull != null) {
checkArgument(valueIsNull.length >= positionOffset + positionCount,
"isNull array too small: need %d, got %d", positionOffset + positionCount, valueIsNull.length);
} Type guard
boolean nullBitmapCovers(boolean[] valueIsNull, int positionOffset, int positionCount) {
return valueIsNull == null || valueIsNull.length >= positionOffset + positionCount;
} Try / catch
try {
block = new Int128ArrayBlock(offset, count, isNull, values);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("isNull length is less than positionCount")) {
isNull = Arrays.copyOfRange(isNull, 0, offset + count); // pad and retry
block = new Int128ArrayBlock(offset, count, isNull, values);
} else { throw e; }
} Prevention
- Slice isNull arrays with the same offset/length used for positions when building regions.
- Assert all per-column arrays (values, isNull) have matching lengths before constructing blocks.
- Never trim the null channel independently of the value channel.
When it happens
Trigger: Passing a valueIsNull array sized for the original block but a positionOffset/positionCount describing a larger region; allocating valueIsNull as positionCount while using a nonzero positionOffset; passing an array trimmed by a previous compaction.
Common situations: Region/view construction where isNull was sliced but positions were not (or vice versa); page serialization round-trips that shrink the null channel; building blocks from columns of mismatched lengths.
Related errors
- positionOffset is negative
- positionCount is negative
- values length is less than positionCount
- isNull length is less than positionCount
- arrayOffset is negative
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/c35ce4465bed6f6a.
Report an issue: GitHub.