prestodb/presto · error · IllegalArgumentException
offset must be 0 or 8
Error message
offset must be 0 or 8
What it means
getLong(position, offset) on Int128ArrayBlockBuilder exposes the two 64-bit halves of a 128-bit integer; only offsets 0 (high word) and 8 (low word) are meaningful because values are stored as pairs of longs. Any other offset is a protocol violation and throws IllegalArgumentException.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlockBuilder.java:225
}
@Override
public int getPositionCount()
{
return positionCount;
}
@Override
public long getLong(int position, int offset)
{
checkReadablePosition(position);
if (offset == 0) {
return values[position * 2];
}
if (offset == 8) {
return values[(position * 2) + 1];
}
throw new IllegalArgumentException("offset must be 0 or 8");
}
/**
* Get the Slice starting at {@code this.positionOffset + offset} in the value at {@code position} with {@code length} bytes.
*
* @param position The logical position of the 128-bit integer in the values array.
* For example, position = 0 refers to the 128-bit integer at values[2] and values[3] if this.positionOffset = 1.
* @param offset The offset to the position in the unit of 128-bit integers.
* For example, offset = 1 means the next position (one 128-bit integer or 16 bytes) to the specified position.
* This means we always compare bytes starting at 128-bit integer boundaries.
* @param length The length in bytes. It has to be a multiple of 16.
*/
@Override
public Slice getSlice(int position, int offset, int length)
{
checkValidRegion(positionCount, offset, length / SIZE_OF_LONG / 2);
return getSliceUnchecked(position + getOffsetBase(), offset, length);
}View on GitHub (pinned to 55bb57d202)
Solutions
- Pass only 0 or 8 as offset; use getLong(position, 0) and getLong(position, 8) for the two halves.
- For multi-byte reads use getLongUnchecked internal position API or getSlice/getBytesRange instead of arbitrary offsets.
- Fix offset computation in generic readers to treat 128-bit ints as two long words.
Example fix
// before long v = blockBuilder.getLong(position, 4); // IllegalArgumentException // after long high = blockBuilder.getLong(position, 0); long low = blockBuilder.getLong(position, 8);
Defensive patterns
Strategy: validation
Validate before calling
if (offset != 0 && offset != 8) {
throw new IllegalArgumentException("Int128 offsets must be 0 or 8, got " + offset);
}
long v = block.getLong(position, offset); Try / catch
try {
long v = block.getLong(position, offset);
} catch (IllegalArgumentException e) {
// fall back to reading both halves
long high = block.getLong(position, 0);
long low = block.getLong(position, 8);
} Prevention
- Remember Int128 blocks expose two long words, not byte offsets
- Wrap Int128 reads in helper methods that only accept 0/8
- Do not reuse Slice-style byte-offset logic against Int128 blocks
When it happens
Trigger: Calling getLong(position, offset) with offset values other than 0 or 8 — e.g. byte-level offsets like 4 or 16, or passing a byte offset computed for a Slice-based block.
Common situations: Generic block-reading code written for VariableWidthBlock (byte offsets) reused against Int128ArrayBlockBuilder; hand-written SerDe loops that advance an offset by 4 bytes per int.
Related errors
- offset must be 0 or 8
- otherOffset %d, length %d are invalid for otherSlice with le
- Offset is not monotonically ascending. offsets[%s]=%s, offse
- A null map must have zero entries
- Number of fields in RowBlock must be positive
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/0730464ed62bf299.
Report an issue: GitHub.