prestodb/presto · error · IllegalStateException

Expected AbstractSingleRowBlock

Error message

Expected AbstractSingleRowBlock

What it means

appendStructure(Block) copies an existing single-row block into this RowBlockBuilder. It only accepts AbstractSingleRowBlock instances (e.g. SingleRowBlock or RowBlock's single-position views); any other Block cannot be interpreted as one row of fields, so the library throws IllegalStateException instead of guessing the layout.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/RowBlockBuilder.java:270

        }
        Block[] fieldBlocks = new Block[numFields];
        for (int i = 0; i < numFields; i++) {
            fieldBlocks[i] = fieldBlockBuilders[i].build();
        }
        return createRowBlockInternal(0, positionCount, hasNullRow ? rowIsNull : null, fieldBlockOffsets, fieldBlocks);
    }

    @Override
    public String toString()
    {
        return format("RowBlockBuilder(%d){numFields=%d, positionCount=%d", hashCode(), numFields, getPositionCount());
    }

    @Override
    public BlockBuilder appendStructure(Block block)
    {
        if (!(block instanceof AbstractSingleRowBlock)) {
            throw new IllegalStateException("Expected AbstractSingleRowBlock");
        }
        if (currentEntryOpened) {
            throw new IllegalStateException("Expected current entry to be closed but was opened");
        }
        currentEntryOpened = true;

        int blockPositionCount = block.getPositionCount();
        if (blockPositionCount != numFields) {
            throw new IllegalArgumentException(format("block position count (%s) is not equal to number of fields (%s)", blockPositionCount, numFields));
        }
        for (int i = 0; i < blockPositionCount; i++) {
            if (block.isNull(i)) {
                fieldBlockBuilders[i].appendNull();
            }
            else {
                block.writePositionTo(i, fieldBlockBuilders[i]);
            }
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Ensure the argument is a single-position row block (check block instanceof AbstractSingleRowBlock before calling)
  2. If the block is a multi-position row, iterate positions and copy fields per position
  3. If data is in plain column blocks, build the row via beginBlockEntry/field writes instead of appendStructure
  4. Unwrap known wrappers (RunLengthEncodedBlock, DictionaryBlock) to the underlying single row

Example fix

// before
rowBuilder.appendStructure(valuesBlock); // valuesBlock is IntArrayBlock -> IllegalStateException
// after
checkState(valuesBlock.getPositionCount() == 1 && valuesBlock instanceof AbstractSingleRowBlock);
rowBuilder.appendStructure((AbstractSingleRowBlock) valuesBlock);
Defensive patterns

Strategy: type-guard

Validate before calling

// before appendStructure
checkState(block instanceof AbstractSingleRowBlock,
    "appendStructure requires a single-row block, got %s", block.getClass().getSimpleName());
checkState(block.getPositionCount() == 1 || block instanceof AbstractSingleRowBlock);

Type guard

boolean isSingleRowBlock(Block block) {
    return block instanceof AbstractSingleRowBlock;
}

Try / catch

try {
    rowBuilder.appendStructure(block);
} catch (IllegalStateException e) {
    if (e.getMessage().equals("Expected AbstractSingleRowBlock")) {
        // fall back to field-by-field copy via beginBlockEntry
        appendFieldsManually(rowBuilder, block);
        return;
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing a non-row Block (e.g. an IntArrayBlock, a dictionary-encoded block, or a multi-position RowBlock) to RowBlockBuilder.appendStructure().

Common situations: Code appending values into row-typed columns that received a flattened or re-encoded block from an upstream operator (e.g. after exchange or lazy materialization changes the wrapper type).

Related errors


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