prestodb/presto · error · UnsupportedOperationException

SingleMapBlock does not support appendNull()

Error message

SingleMapBlock does not support appendNull()

What it means

SingleMapBlock represents a single map entry backed by an immutable MapBlock and does not support mutation. Calling appendNull() throws UnsupportedOperationException because appending a null row to a view over an existing map would violate the block's immutability contract.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/SingleMapBlock.java:161

    public Block getValueBlock()
    {
        return mapBlock.getRawValueBlock().getRegion(positionInMap, positionCount / 2);
    }

    public Block getBaseMapBlock()
    {
        return mapBlock;
    }

    public int getPositionInMap()
    {
        return positionInMap;
    }

    @Override
    public Block appendNull()
    {
        throw new UnsupportedOperationException("SingleMapBlock does not support appendNull()");
    }

    @Nullable
    int[] getHashTable()
    {
        return mapBlock.getHashTables().get();
    }

    /**
     * @return position of the value under {@code nativeValue} key. -1 when key is not found.
     */
    public int seekKey(Object nativeValue, MethodHandle keyNativeHashCode, MethodHandle keyBlockNativeEquals, MethodHandle keyBlockHashCode)
    {
        if (positionCount == 0) {
            return -1;
        }

        mapBlock.ensureHashTableLoaded(keyBlockHashCode);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Use a MapBlockBuilder (or generic BlockBuilder for the map type) and construct null/empty maps there instead of calling appendNull on the SingleMapBlock.
  2. Detect immutable blocks before appending: check instanceof SingleMapBlock and use a builder-based path.
  3. Copy values via writePositionTo into a new builder rather than append on the source block.

Example fix

// before
Block value = mapColumn.getBlock(position);
Block out = value.appendNull(); // UnsupportedOperationException
// after
MapBlockBuilder out = (MapBlockBuilder) type.createBlockBuilder(null, 1);
out.appendNull(); // appends a NULL map row to the builder
value.writePositionTo(position, /* use a dedicated builder */ null); // copy instead of mutate
Defensive patterns

Strategy: type-guard

Validate before calling

if (block instanceof SingleMapBlock || block instanceof SingleRowBlock) {
    // immutable view: copy into a builder instead of appending
}

Type guard

boolean isMutableBlock(Block block) {
    return !(block instanceof SingleMapBlock) && !(block instanceof SingleRowBlock) && !(block instanceof AbstractSingleArrayBlock);
}

Try / catch

try {
    newBlock = block.appendNull();
} catch (UnsupportedOperationException e) {
    BlockBuilder builder = type.createBlockBuilder(null, block.getPositionCount() + 1);
    block.writePositionTo(position, builder);
    builder.appendNull();
    newBlock = builder.build();
}

Prevention

When it happens

Trigger: Calling appendNull() on a SingleMapBlock, typically in generic Block-merging or null-padding code that assumes all Block types are mutable.

Common situations: Generic block-combining algorithms (e.g. building output pages row by row) hitting a map-typed column; code that copies blocks via append* assuming uniform API; accidentally using SingleMapBlock where MapBlockBuilder was intended.

Related errors


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