prestodb/presto · error · IllegalArgumentException

values length is less than positionCount

Error message

values length is less than positionCount

What it means

Int128 values occupy 2 longs each, so the values array must hold at least positionCount*2 longs beyond the positionOffset (which is also in positions, i.e. offset*2 longs). The constructor throws IllegalArgumentException when the backing array is too small, preventing out-of-bounds reads later.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/Int128ArrayBlock.java:74

    public Int128ArrayBlock(int positionCount, Optional<boolean[]> valueIsNull, long[] values)
    {
        this(0, positionCount, valueIsNull.orElse(null), values);
    }

    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

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Allocate values with capacity 2 * (positionOffset + positionCount) longs.
  2. Double-check every allocation site for Int128 blocks multiplies the position count by 2 (INT128 = two longs).
  3. If reusing a buffer, grow it (Arrays.copyOf) when values.length < 2 * (positionOffset + positionCount).

Example fix

// before
long[] values = new long[positionCount]; // too small for 128-bit values
// after
long[] values = new long[2 * (positionOffset + positionCount)];
Defensive patterns

Strategy: validation

Validate before calling

checkArgument(values.length >= 2 * (positionOffset + positionCount),
    "values array too small: need %d longs for %d INT128 positions, got %d",
    2 * (positionOffset + positionCount), positionCount, values.length);

Type guard

boolean valuesSizedForInt128(long[] values, int positionOffset, int positionCount) {
    return values.length >= 2 * (positionOffset + positionCount);
}

Try / catch

try {
    block = new Int128ArrayBlock(offset, count, isNull, values);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("values length is less than positionCount")) {
        values = Arrays.copyOf(values, 2 * (offset + count));
        block = new Int128ArrayBlock(offset, count, isNull, values);
    } else { throw e; }
}

Prevention

When it happens

Trigger: new Int128ArrayBlock(positionOffset, positionCount, valueIsNull, values) where values.length - positionOffset*2 < positionCount*2 — e.g. allocating values as positionCount longs instead of 2*positionCount, or forgetting to account for a non-zero positionOffset.

Common situations: Custom block builders allocating 1 long per position instead of 2 for 128-bit types (DECIMAL(38,x)); reusing buffers trimmed to a smaller previous batch; slicing code that applies the offset to positions but not to the array length calculation.

Related errors


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