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

  1. Pass only 0 or 8 as offset; use getLong(position, 0) and getLong(position, 8) for the two halves.
  2. For multi-byte reads use getLongUnchecked internal position API or getSlice/getBytesRange instead of arbitrary offsets.
  3. 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

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


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/0730464ed62bf299. Report an issue: GitHub.