prestodb/presto · error · IllegalArgumentException

position is not valid: " + position

Error message

position is not valid: " + position

What it means

AbstractSingleMapBlock.getAbsolutePosition maps a caller-supplied position into the underlying key/value block position space. If position is negative or >= getPositionCount() (which is 2 for a single-entry map: one key, one value), it throws IllegalArgumentException including the offending position value.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/AbstractSingleMapBlock.java:34

import io.airlift.slice.Slice;
import io.airlift.slice.SliceOutput;

import static com.facebook.presto.common.block.BlockUtil.internalPositionInRange;

public abstract class AbstractSingleMapBlock
        implements Block
{
    abstract int getOffset();

    abstract Block getRawKeyBlock();

    abstract Block getRawValueBlock();

    private int getAbsolutePosition(int position)
    {
        if (position < 0 || position >= getPositionCount()) {
            throw new IllegalArgumentException("position is not valid: " + position);
        }
        return position + getOffset();
    }

    @Override
    public boolean isNull(int position)
    {
        position = getAbsolutePosition(position);
        if (position % 2 == 0) {
            if (getRawKeyBlock().isNull(position / 2)) {
                throw new IllegalStateException("Map key is null at position: " + position);
            }
            return false;
        }
        else {
            return getRawValueBlock().isNull(position / 2);
        }
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Only pass 0 (key) or 1 (value) positions to a single-map block, or use typed accessor APIs.
  2. Fix callers to map logical key/value indices to the 0/1 positions of the single-map block.
  3. Add bounds checks in the calling operator before invoking raw block getters.

Example fix

// before
int rawPos = mapBlock.getPositionCount(); // e.g. out-of-range index
mapBlock.getInt(rawPos);
// after
int rawPos = Math.min(entryIndex, mapBlock.getPositionCount() - 1);
checkArgument(rawPos >= 0, "entry index out of range");
mapBlock.getInt(rawPos);
Defensive patterns

Strategy: type-guard

Validate before calling

static boolean isValidSingleMapPosition(Block mapBlock, int position) {
    return position >= 0 && position < mapBlock.getPositionCount(); // 0 = key, 1 = value
}

Type guard

static boolean canAccessEntry(Block singleMapBlock, int position) {
    return position == 0 || position == 1;
}

Try / catch

try {
    long v = mapBlock.getLong(position);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("position is not valid")) {
        throw new IndexOutOfBoundsException("single map position out of range: " + e.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling isNull/getByte/getShort/getInt/getLong/getSlice on a single-map block with a position outside [0, 2); typically from passing array- or row-style positions, or raw key-block positions.

Common situations: Custom accessors for map entries treating the block as a general block with many positions; expression evaluation bugs reading key/value at wrong indices.

Related errors


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