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
- Use a MapBlockBuilder (or generic BlockBuilder for the map type) and construct null/empty maps there instead of calling appendNull on the SingleMapBlock.
- Detect immutable blocks before appending: check instanceof SingleMapBlock and use a builder-based path.
- 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
- Never call append* on blocks returned from getBlock/getRegion — treat them as immutable views.
- For output assembly, always go through a BlockBuilder of the correct type.
- Document in shared utilities that Single*Block types are read-only.
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
- SingleRowBlock does not support appendNull()
- New column does not have same number of rows as old column
- Declared positions (%s) does not match block %s's number of
- Offset is not monotonically ascending. offsets[%s]=%s, offse
- A null map must have zero entries
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/8923d806ad75bc18.
Report an issue: GitHub.