prestodb/presto · error · IllegalArgumentException
otherOffset %d, length %d are invalid for otherSlice with le
Error message
otherOffset %d, length %d are invalid for otherSlice with length %d
What it means
bytesEqual compares a 128-bit value region of this block against a byte range of another Slice. The otherOffset/length pair must lie entirely within otherSlice (both non-negative and otherOffset + length <= otherSlice.length()); otherwise the comparison would read past the slice, so IllegalArgumentException is thrown.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlock.java:213
* Is the byte sequences at the {@code position + offset} position in the 128-bit values of {@code length} bytes equal
* to the byte sequence at {@code otherOffset} in {@code otherSlice}.
*
* @param position The position of 128-bit integer.
* @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 starting at 128-bit integer boundaries.
* @param otherSlice The slice to compare to.
* @param otherOffset The offset in bytes to the start of otherSlice.
* @param length The length to compare in bytes. It has to be a multiple of 16.
* @return True if the bytes are the same, false otherwise.
*/
@Override
public boolean bytesEqual(int position, int offset, Slice otherSlice, int otherOffset, int length)
{
int num128Integers = getNum128Integers(length);
checkValidRegion(positionCount, position + offset, num128Integers);
if (otherOffset < 0 || length < 0 || otherOffset + length > otherSlice.length()) {
throw new IllegalArgumentException(format("otherOffset %d, length %d are invalid for otherSlice with length %d", otherOffset, length, otherSlice.length()));
}
int currentPosition = (position + offset + positionOffset) * 2;
for (int i = 0; i < num128Integers; i++) {
if (values[currentPosition] != otherSlice.getLong(otherOffset) || values[currentPosition + 1] != otherSlice.getLong(otherOffset + SIZE_OF_LONG)) {
return false;
}
currentPosition += 2;
otherOffset += SIZE_OF_LONG * 2;
}
return true;
}
@Override
public boolean mayHaveNull()
{View on GitHub (pinned to 55bb57d202)
Solutions
- Slice otherSlice to exactly the value being compared before calling: otherSlice = slice.slice(valueStart, INT128_BYTES).
- Validate otherOffset >= 0 && length >= 0 && otherOffset + length <= otherSlice.length() at the call site.
- Ensure length is a multiple of 16 for INT128 comparisons (getNum128Integers expects this).
Example fix
// before block.bytesEqual(pos, 0, bigSlice, rawOffset, 8); // wrong length/bounds // after Slice value = bigSlice.slice(valueStart, Int128ArrayBlock.INT128_BYTES); block.bytesEqual(pos, 0, value, 0, Int128ArrayBlock.INT128_BYTES);
Defensive patterns
Strategy: validation
Validate before calling
checkArgument(otherOffset >= 0 && length >= 0 && otherOffset + length <= otherSlice.length(),
"bytesEqual range [%d, %d) out of slice length %d", otherOffset, otherOffset + length, otherSlice.length()); Type guard
boolean sliceRangeInBounds(Slice slice, int offset, int length) {
return offset >= 0 && length >= 0 && offset + length <= slice.length();
} Try / catch
try {
equal = block.bytesEqual(position, 0, otherSlice, otherOffset, length);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("are invalid for otherSlice")) {
throw new IllegalStateException("comparison slice not aligned to INT128 value boundaries", e);
}
throw e;
} Prevention
- Always slice the comparison Slice to exactly the value (16 bytes) before bytesEqual.
- Use the type's fixed size constant (INT128_BYTES) for lengths, not the raw slice length.
- Cover DECIMAL equality/hash operators with tests using boundary slices.
When it happens
Trigger: Calling Int128ArrayBlock.bytesEqual(position, offset, otherSlice, otherOffset, length) where otherOffset < 0, length < 0, or otherOffset + length > otherSlice.length() — e.g. passing a Slice not sliced to the value boundary, or a length other than 16 in 128-bit comparisons.
Common situations: Hash/equality operators passing raw slices without adjusting an offset for the value start; comparing DECIMAL values against varbinary slices whose lengths differ; forgetful slicing after copying a sub-range of a larger buffer.
Related errors
- position is not valid
- position is not valid
- position is not valid: " + position
- position is not valid: " + position
- offset must be 0 or 8
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/176aaa72bce23fe5.
Report an issue: GitHub.