prestodb/presto · error · IllegalArgumentException

Invalid map block:

Error message

Invalid map block: 

What it means

ColumnarMap.toColumnarMap only understands map blocks that extend AbstractMapBlock (plus RunLengthEncodedBlock). When handed a Block of any other concrete type (e.g. a plain BlockBuilder output, IntArrayBlock, or a decoded/lazy block that was not yet compaction into a map representation), it throws IllegalArgumentException with the offending class name appended. This is a defensive type check because the method casts the block to AbstractMapBlock immediately afterwards.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/ColumnarMap.java:47

    private final Block keysBlock;
    private final Block valuesBlock;
    private final int[] hashTables;
    private final long retainedSizeInBytes;
    private final long estimatedSerializedSizeInBytes;

    public static ColumnarMap toColumnarMap(Block block)
    {
        requireNonNull(block, "block is null");

        if (block instanceof DictionaryBlock) {
            return toColumnarMap((DictionaryBlock) block);
        }
        if (block instanceof RunLengthEncodedBlock) {
            return toColumnarMap((RunLengthEncodedBlock) block);
        }

        if (!(block instanceof AbstractMapBlock)) {
            throw new IllegalArgumentException("Invalid map block: " + block.getClass().getName());
        }

        AbstractMapBlock mapBlock = (AbstractMapBlock) block;

        int offsetBase = mapBlock.getOffsetBase();
        int[] offsets = mapBlock.getOffsets();

        // get the keys and values for visible region
        int firstEntryPosition = mapBlock.getOffset(0);
        int totalEntryCount = mapBlock.getOffset(block.getPositionCount()) - firstEntryPosition;
        Block keysBlock = mapBlock.getRawKeyBlock().getRegion(firstEntryPosition, totalEntryCount);
        Block valuesBlock = mapBlock.getRawValueBlock().getRegion(firstEntryPosition, totalEntryCount);
        int[] hashTables = mapBlock.getHashTables().get();

        return new ColumnarMap(
                block,
                offsetBase,
                offsets,

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Verify the Block being passed is actually a MAP-typed column (check the Type of the page column before converting)
  2. Call LazyBlock.unwrap() on the block (or Page.getBlock) before invoking toColumnarMap so lazy/dictionary-decorated blocks resolve to the real AbstractMapBlock
  3. Ensure custom Block implementations for maps extend AbstractMapBlock
  4. Check the exception message for the actual class name of the block and fix the upstream code producing that block

Example fix

// before
Block block = page.getBlock(1);
ColumnarMap map = ColumnarMap.toColumnarMap(block); // throws if lazy/unwrapped
// after
Block block = page.getBlock(1).getLoadedBlock();
checkArgument(block instanceof AbstractMapBlock || block instanceof RunLengthEncodedBlock, "Expected map block, got %s", block.getClass().getSimpleName());
ColumnarMap map = ColumnarMap.toColumnarMap(block);
Defensive patterns

Strategy: type-guard

Validate before calling

public static ColumnarMap safeToColumnarMap(Block block)
{
    Block loaded = block.getLoadedBlock();
    checkArgument(loaded instanceof AbstractMapBlock || loaded instanceof RunLengthEncodedBlock,
        "Expected map block, got %s", loaded.getClass().getName());
    return ColumnarMap.toColumnarMap(loaded);
}

Type guard

static boolean isMapBlock(Block block) {
    Block b = block.getLoadedBlock();
    return b instanceof AbstractMapBlock || b instanceof RunLengthEncodedBlock;
}

Try / catch

try {
    ColumnarMap map = ColumnarMap.toColumnarMap(block);
} catch (IllegalArgumentException e) {
    throw new IllegalStateException("Cannot convert column to map: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling ColumnarMap.toColumnarMap(block) or ColumnarMap.columnarMap(block) with a Block that is neither a RunLengthEncodedBlock nor an AbstractMapBlock — e.g. passing the wrong-typed column of a page, a block produced by a non-map writer, or an unwrapped lazy block.

Common situations: Page/column type mismatches in custom connectors or readers (e.g. ORC/Parquet readers that decode a MAP column into the wrong block class); skipping the LazyBlock.unwrap call before extracting columns; version changes where a custom Block implementation no longer extends AbstractMapBlock.

Related errors


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