prestodb/presto · error · IllegalArgumentException

isNull length is less than positionCount

Error message

isNull length is less than positionCount

What it means

ByteArrayBlock's constructor validates that, when a null-value map (valueIsNull) is supplied, it has at least positionCount entries after arrayOffset. If valueIsNull.length - arrayOffset < positionCount, the block could not answer isNull(position) for every valid position, so the library throws IllegalArgumentException. Passing null for valueIsNull is allowed and means no value is null.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/ByteArrayBlock.java:80

    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));
    }

    @Override
    public long getSizeInBytes()
    {
        return SIZE_IN_BYTES_PER_POSITION * (long) positionCount;
    }

    @Override
    public long getRegionSizeInBytes(int position, int length)
    {
        return SIZE_IN_BYTES_PER_POSITION * (long) length;
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Ensure valueIsNull.length - arrayOffset >= positionCount, or allocate valueIsNull = new boolean[positionCount]
  2. Pass null for valueIsNull if no values are null (avoids the check and reduces retained size)
  3. Resize the null mask before construction, e.g. Arrays.copyOf(isNull, positionCount)
  4. Audit where the null mask is produced so its length always matches the values batch

Example fix

// before
new ByteArrayBlock(100, Optional.of(new boolean[64]), values, null); // throws
// after
new ByteArrayBlock(100, Optional.of(new boolean[100]), values, null);
Defensive patterns

Strategy: validation

Validate before calling

if (valueIsNull != null && valueIsNull.length - arrayOffset < positionCount) {
    valueIsNull = Arrays.copyOfRange(valueIsNull, 0, positionCount); // pad to required length
}
Block block = new ByteArrayBlock(positionCount, Optional.ofNullable(valueIsNull), values);

Type guard

boolean nullMaskCovers(boolean[] valueIsNull, int positionCount, int arrayOffset) {
    return valueIsNull == null || valueIsNull.length - arrayOffset >= positionCount;
}

Try / catch

try {
    Block block = new ByteArrayBlock(positionCount, Optional.ofNullable(valueIsNull), values);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("null mask length must cover positionCount: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling new ByteArrayBlock(positionCount, valueIsNull, values, ...) with a valueIsNull array shorter than positionCount (minus arrayOffset); reusing a null map built for a smaller batch; supplying a valueIsNull array after slicing with an arrayOffset but forgetting to grow the array.

Common situations: Vectorized writers writing per-chunk null masks sized to the chunk not the block; serializers copying a null bitmap of the wrong bit-length; code paths that build valueIsNull only for nullable columns and pass an undersized stale array.

Related errors


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