prestodb/presto · error · IllegalArgumentException
arrayOffset is negative
Error message
arrayOffset is negative
What it means
The package-private ByteArrayBlock constructor validates its arrayOffset parameter and throws this IllegalArgumentException if it is negative. arrayOffset is the starting index into the shared byte[] values array; a negative offset would make all position math invalid. It is a defensive precondition against malformed construction arguments.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/ByteArrayBlock.java:66
public static final int SIZE_IN_BYTES_PER_POSITION = Byte.BYTES + Byte.BYTES;
private final int arrayOffset;
private final int positionCount;
@Nullable
private final boolean[] valueIsNull;
private final byte[] values;
private final long retainedSizeInBytes;
public ByteArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, byte[] values)
{
this(0, positionCount, valueIsNull.orElse(null), values);
}
ByteArrayBlock(int arrayOffset, int positionCount, boolean[] valueIsNull, byte[] 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));View on GitHub (pinned to 55bb57d202)
Solutions
- Fix the offset computation so it is never negative; clamp with Math.max(0, offset) only if a negative value is legitimate 'no data' semantics.
- If the intent was an empty view, pass arrayOffset 0 with positionCount 0 instead of a negative offset.
- Audit the code that wraps sub-arrays and add an explicit assertion offset >= 0 near the slice computation.
Example fix
// before int offset = previousEnd - sliceSize; // can go negative new ByteArrayBlock(offset, count, valueIsNull, values); // after int offset = Math.max(0, previousEnd - sliceSize); checkArgument(offset >= 0, "computed slice offset is negative"); new ByteArrayBlock(offset, count, valueIsNull, values);
Defensive patterns
Strategy: validation
Validate before calling
if (arrayOffset < 0) {
throw new IllegalArgumentException("computed arrayOffset is negative: " + arrayOffset);
}
new ByteArrayBlock(arrayOffset, positionCount, valueIsNull, values); Type guard
boolean isValidBlockArgs(int arrayOffset, int positionCount) {
return arrayOffset >= 0 && positionCount >= 0;
} Try / catch
try {
block = new ByteArrayBlock(arrayOffset, positionCount, valueIsNull, values);
} catch (IllegalArgumentException e) {
if (e.getMessage().equals("arrayOffset is negative")) {
throw new IllegalStateException("negative slice offset from " + offsetSource, e);
} else {
throw e;
}
} Prevention
- Clamp or assert slice offsets with Math.max(0, ...) / checkArgument(offset >= 0) at the slicing site.
- Avoid reusing offset accumulators across iterations without resetting them.
- Use 0 offset with positionCount 0 to represent an empty view.
- Add range assertions in any custom code that wraps sub-arrays of larger buffers.
When it happens
Trigger: Constructing ByteArrayBlock (directly in package code, or via the public constructor paths that forward) with a negative arrayOffset, usually from bad offset arithmetic when wrapping a sub-range of a larger byte buffer.
Common situations: Custom connector code slicing a page/buffer with a computed offset that underflowed (offset -= size going negative); reusing offset variables across loops; buggy serialization/deserialization code that reconstructs blocks with incorrect offsets.
Understand the failure class
Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.
Related errors
- positionCount is negative
- array1 and array2 cannot be null and should have same length
- positionCount is negative
- ids length is less than positionCount
- New column does not have same number of rows as old column
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/cb35e9334cf3e8e3.
Report an issue: GitHub.