prestodb/presto · error · IllegalArgumentException
Invalid row block:
Error message
Invalid row block:
What it means
ColumnarRow.toColumnarRow only supports row blocks extending AbstractRowBlock (plus RunLengthEncodedBlock). Any other Block implementation reaches a hard cast and would fail, so the method throws IllegalArgumentException with the block's class name. It guarantees the subsequent field access methods (getFieldBlockOffset, etc.) are valid.
Source
Thrown at presto-common/src/main/java/com/facebook/presto/common/block/ColumnarRow.java:42
private final Block nullCheckBlock;
private final Block[] fields;
private final long retainedSizeInBytes;
private final long estimatedSerializedSizeInBytes;
public static ColumnarRow toColumnarRow(Block block)
{
requireNonNull(block, "block is null");
if (block instanceof DictionaryBlock) {
return toColumnarRow((DictionaryBlock) block);
}
if (block instanceof RunLengthEncodedBlock) {
return toColumnarRow((RunLengthEncodedBlock) block);
}
if (!(block instanceof AbstractRowBlock)) {
throw new IllegalArgumentException("Invalid row block: " + block.getClass().getName());
}
AbstractRowBlock rowBlock = (AbstractRowBlock) block;
// get fields for visible region
int firstRowPosition = rowBlock.getFieldBlockOffset(0);
int totalRowCount = rowBlock.getFieldBlockOffset(block.getPositionCount()) - firstRowPosition;
Block[] fieldBlocks = new Block[rowBlock.numFields];
for (int i = 0; i < fieldBlocks.length; i++) {
fieldBlocks[i] = rowBlock.getRawFieldBlocks()[i].getRegion(firstRowPosition, totalRowCount);
}
return new ColumnarRow(block, fieldBlocks, block.getRetainedSizeInBytes(), block.getSizeInBytes());
}
private static ColumnarRow toColumnarRow(DictionaryBlock dictionaryBlock)
{
// build a mapping from the old dictionary to a new dictionary with nulls removedView on GitHub (pinned to 55bb57d202)
Solutions
- Unwrap lazy blocks (block.getLoadedBlock() / LazyBlock.unwrap()) before converting
- Confirm the page column's Type is RowType and its block is a row block before calling toColumnarRow
- Make custom row Block implementations extend AbstractRowBlock
- Read the exception message for the concrete class name and trace where that block is produced
Example fix
// before ColumnarRow row = ColumnarRow.toColumnarRow(rawBlock); // after Block block = rawBlock.getLoadedBlock(); checkArgument(block instanceof AbstractRowBlock || block instanceof RunLengthEncodedBlock, "Expected row block, got %s", block.getClass().getSimpleName()); ColumnarRow row = ColumnarRow.toColumnarRow(block);
Defensive patterns
Strategy: type-guard
Validate before calling
public static ColumnarRow safeToColumnarRow(Block block)
{
Block loaded = block.getLoadedBlock();
checkArgument(loaded instanceof AbstractRowBlock || loaded instanceof RunLengthEncodedBlock,
"Expected row block, got %s", loaded.getClass().getName());
return ColumnarRow.toColumnarRow(loaded);
} Type guard
static boolean isRowBlock(Block block) {
Block b = block.getLoadedBlock();
return b instanceof AbstractRowBlock || b instanceof RunLengthEncodedBlock;
} Try / catch
try {
ColumnarRow row = ColumnarRow.toColumnarRow(block);
} catch (IllegalArgumentException e) {
throw new IllegalStateException("Cannot convert column to row: " + e.getMessage(), e);
} Prevention
- Check the column Type is RowType before conversion
- Unwrap lazy/dictionary-decorated blocks first
- Pass the top-level row block, not a nested field block
- Ensure custom row blocks extend AbstractRowBlock
When it happens
Trigger: Calling ColumnarRow.toColumnarRow(block) or ColumnarRow.columnarRow(block) with a Block that is neither RunLengthEncodedBlock nor AbstractRowBlock — e.g. a ROW column encoded as dictionary or plain array block, or an unwrapped lazy block of the wrong concrete type.
Common situations: Connector/page deserialization bugs where a ROW column arrives as a different block class; forgetting to unwrap LazyBlock; passing an element block instead of the top-level row block; upgrading Presto where custom row block implementations were removed.
Related errors
- Invalid map block:
- Invalid row block
- ELASTICSEARCH_TYPE_MISMATCH
- New column does not have same number of rows as old column
- Declared positions (%s) does not match block %s's number of
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/35c3c5f163bea268.
Report an issue: GitHub.