prestodb/presto · error · IllegalArgumentException

Number of fields in RowBlock must be positive

Error message

Number of fields in RowBlock must be positive

What it means

A RowBlock must have at least one field column; the AbstractRowBlock constructor rejects numFields <= 0 because a row type with zero fields cannot be represented in field blocks. This is a construction-time validation of the row type's arity.

Source

Thrown at presto-common/src/main/java/com/facebook/presto/common/block/AbstractRowBlock.java:58

    public abstract int getOffsetBase();

    /**
     * @return the underlying rowIsNull array, or null when all rows are guaranteed to be non-null
     */
    @Nullable
    protected abstract boolean[] getRowIsNull();

    // the offset in each field block, it can also be viewed as the "entry-based" offset in the RowBlock
    protected final int getFieldBlockOffset(int position)
    {
        return getFieldBlockOffsets()[position + getOffsetBase()];
    }

    protected AbstractRowBlock(int numFields)
    {
        if (numFields <= 0) {
            throw new IllegalArgumentException("Number of fields in RowBlock must be positive");
        }
        this.numFields = numFields;
    }

    @Override
    public String getEncodingName()
    {
        return RowBlockEncoding.NAME;
    }

    @Override
    public final Block copyPositions(int[] positions, int offset, int length)
    {
        checkArrayRange(positions, offset, length);

        int[] newOffsets = new int[length + 1];
        int[] fieldBlockPositions = new int[length];
        boolean[] newRowIsNull = null;

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Ensure the RowType has at least one field before constructing the corresponding row block.
  2. Fix upstream metadata so empty schemas are rejected or given a placeholder field instead of becoming a zero-field row type.
  3. Guard the code path: if fieldBlocks.length == 0, handle it before calling the block factory.

Example fix

// before
Block[] fieldBlocks = collectFieldBlocks(rowType); // may be empty
RowBlock block = RowBlock.fromFieldBlocks(0, new boolean[] {}, fieldBlocks);
// after
checkState(!rowType.getFields().isEmpty(), "row type must have at least one field");
Block[] fieldBlocks = collectFieldBlocks(rowType);
RowBlock block = RowBlock.fromFieldBlocks(0, new boolean[] {}, fieldBlocks);
Defensive patterns

Strategy: validation

Validate before calling

if (fieldBlocks == null || fieldBlocks.length == 0) {
    throw new IllegalStateException("cannot build a row block with zero fields");
}

Type guard

boolean hasFields(RowType rowType) {
    return rowType != null && !rowType.getFields().isEmpty();
}

Try / catch

try {
    RowBlock block = RowBlock.fromFieldBlocks(positionCount, rowIsNull, fieldBlocks);
} catch (IllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("must be positive")) {
        throw new SchemaException("row type has no fields", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Constructing a row block (RowBlock.fromFieldBlocks, encoder/decoder paths) with a RowType that has zero fields, or passing an empty field-block array.

Common situations: Dynamically building a RowType from an empty schema or column list (e.g. a connector returning no columns); metadata/config errors where a row type is created before fields are known.

Related errors


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