prestodb/presto · error · IllegalArgumentException
Expected value to contain a single position but has %s posit
Error message
Expected value to contain a single position but has %s positions
What it means
RunLengthEncodedBlock represents N repetitions of exactly one value, so its constructor requires value.getPositionCount() == 1. Passing a multi-position block is a contract violation; the library throws IllegalArgumentException including the actual count, since it cannot pick which position to repeat.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/RunLengthEncodedBlock.java:55
private static final int INSTANCE_SIZE = ClassLayout.parseClass(RunLengthEncodedBlock.class).instanceSize();
public static Block create(Type type, Object value, int positionCount)
{
Block block = Utils.nativeValueToBlock(type, value);
if (block instanceof RunLengthEncodedBlock) {
block = ((RunLengthEncodedBlock) block).getValue();
}
return new RunLengthEncodedBlock(block, positionCount);
}
private final Block value;
private final int positionCount;
public RunLengthEncodedBlock(Block value, int positionCount)
{
requireNonNull(value, "value is null");
if (value.getPositionCount() != 1) {
throw new IllegalArgumentException(format("Expected value to contain a single position but has %s positions", value.getPositionCount()));
}
if (value instanceof RunLengthEncodedBlock) {
this.value = ((RunLengthEncodedBlock) value).getValue();
}
else {
this.value = value;
}
if (positionCount < 0) {
throw new IllegalArgumentException("positionCount is negative");
}
this.positionCount = positionCount;
}
public Block getValue()
{View on GitHub (pinned to 55bb57d202)
Solutions
- Extract a single-position block first (e.g. value.getSingleValueBlock(0) or RunLengthEncodedBlock wrapping then unwrapping)
- If you have a multi-position block, wrap each position separately or build via a page transform
- Check value.getPositionCount() == 1 before constructing
Example fix
// before RunLengthEncodedBlock rle = new RunLengthEncodedBlock(valuesBlock, count); // valuesBlock has N positions // after RunLengthEncodedBlock rle = new RunLengthEncodedBlock(valuesBlock.getSingleValueBlock(0), count);
Defensive patterns
Strategy: validation
Validate before calling
// before constructing an RLE block
if (value.getPositionCount() != 1) {
throw new IllegalArgumentException("constant must be a single-position block, got " + value.getPositionCount());
}
RunLengthEncodedBlock rle = new RunLengthEncodedBlock(value, n);
Type guard
boolean isSinglePositionBlock(Block b) {
return b.getPositionCount() == 1;
}
Try / catch
try {
return new RunLengthEncodedBlock(value, n);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Expected value to contain a single position")) {
return new RunLengthEncodedBlock(value.getSingleValueBlock(0), n);
}
throw e;
} Prevention
- Use value.getSingleValueBlock(pos) to extract constants from multi-row blocks
- Assert getPositionCount() == 1 when caching constant columns
- Never pass whole page blocks as RLE values
When it happens
Trigger: Passing any Block with positionCount != 1 to new RunLengthEncodedBlock(value, n) — e.g. passing a whole page block or an array block instead of a single-position block.
Common situations: Building constant columns for joins/aggregations where the constant was taken from a multi-row block; misusing getRegion/getPositionBlock results that return multi-position blocks; connector code synthesizing constant columns for predicate pushdown.
Related errors
- positionCount is negative
- position is not valid:
- arrayOffset is negative
- array1 and array2 cannot be null and should have same length
- arrayOffset is negative
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/5e1a8f2729719304.
Report an issue: GitHub.