prestodb/presto · error · IllegalArgumentException

block position count (%s) is not equal to number of fields (

Error message

block position count (%s) is not equal to number of fields (%s)

What it means

appendStructure copies a single-row block field-by-field into the builder, so the incoming block's position count must equal the builder's declared number of fields (numFields). A mismatch means the block's layout cannot map onto the row type, so the library throws IllegalArgumentException with both counts.

Source

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

    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]);
            }
        }

        closeEntry();
        return this;
    }

    @Override
    public BlockBuilder appendStructureInternal(Block block, int position)
    {
        if (!(block instanceof AbstractRowBlock)) {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Verify block.getPositionCount() equals the row type's field count before appending
  2. Ensure the RowType/TypeSignature used to create the builder matches the block's row type
  3. Rebuild the block with the current row type if the schema changed
  4. Use row field mapping/translation code for schema evolution instead of direct append

Example fix

// before
// builder created for RowType(a, b); block has 3 fields
rowBuilder.appendStructure(block); // IllegalArgumentException: 3 != 2
// after
checkArgument(block.getPositionCount() == rowBuilder.getNumFields(), "row arity mismatch");
rowBuilder.appendStructure(block);
Defensive patterns

Strategy: validation

Validate before calling

// before appendStructure, verify arity matches the builder's row type
if (block.getPositionCount() != expectedNumFields) {
    throw new IllegalArgumentException(format(
        "row arity mismatch: block has %s fields, builder expects %s",
        block.getPositionCount(), expectedNumFields));
}

Try / catch

try {
    rowBuilder.appendStructure(block);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("is not equal to number of fields")) {
        // rebuild the row with the expected type rather than appending directly
        throw new IllegalStateException("row type of block does not match builder type; remap fields", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Passing a single-row block built from a different row type (different arity) to appendStructure, e.g. appending a 3-field row into a 2-field row builder after a schema/type change.

Common situations: Schema evolution where a row type gained/lost fields but upstream blocks were built with the old type; dynamic row types whose field count differs across connectors or catalog versions.

Related errors


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