prestodb/presto · error · IllegalArgumentException
Type must be a RowType for StructVector
Error message
Type must be a RowType for StructVector
What it means
assignBlockFromStructVector converts an Arrow StructVector into a Presto row block. It requires the Presto Type to be RowType so it can access the row's field types for recursive per-field conversion; any other Type causes this IllegalArgumentException before any row is written.
Source
Thrown at presto-common-arrow/src/main/java/com/facebook/plugin/arrow/ArrowBlockBuilder.java:752
builder.appendNull();
}
else {
BlockBuilder entryBuilder = builder.beginBlockEntry();
int entryStart = vector.getElementStartIndex(i);
int entryEnd = vector.getElementEndIndex(i);
for (int entryIndex = entryStart; entryIndex < entryEnd; entryIndex++) {
assignBlockFromValueVector(keyVector, mapType.getKeyType(), entryBuilder, entryIndex, entryIndex + 1);
assignBlockFromValueVector(valueVector, mapType.getValueType(), entryBuilder, entryIndex, entryIndex + 1);
}
builder.closeEntry();
}
}
}
public void assignBlockFromStructVector(StructVector vector, Type type, BlockBuilder builder, int startIndex, int endIndex)
{
if (!(type instanceof RowType)) {
throw new IllegalArgumentException("Type must be a RowType for StructVector");
}
RowType rowType = (RowType) type;
for (int i = startIndex; i < endIndex; i++) {
if (vector.isNull(i)) {
builder.appendNull();
}
else {
BlockBuilder childBuilder = builder.beginBlockEntry();
List<Type> childTypes = rowType.getTypeParameters();
for (int childIndex = 0; childIndex < childTypes.size(); childIndex++) {
Type childType = childTypes.get(childIndex);
ValueVector childVector = vector.getChildByOrdinal(childIndex);
assignBlockFromValueVector(childVector, childType, childBuilder, i, i + 1);
}
builder.closeEntry();
}View on GitHub (pinned to 55bb57d202)
Solutions
- Declare the Presto column as a row (RowType) whose fields match the struct's children
- Correct the Type passed via assignBlockFromValueVector so the StructVector gets its RowType
- Ensure the number and types of RowType fields match the StructVector's child vectors
Example fix
// before assignBlockFromStructVector(structVector, VarcharType.VARCHAR, builder, start, end); // after assignBlockFromStructVector(structVector, RowType.from(fieldNames, fieldTypes), builder, start, end);
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(columnType instanceof RowType)) {
throw new IllegalStateException("Column '" + name + "' must be RowType to receive StructVector, got " + columnType);
} Type guard
boolean isRowColumn(Type type) {
return type instanceof RowType;
} Try / catch
try {
builder.assignBlockFromStructVector(vector, type, blockBuilder, start, end);
} catch (IllegalArgumentException e) {
if (!e.getMessage().contains("RowType for StructVector")) throw e;
// re-derive RowType from struct children and retry
} Prevention
- Derive RowType fields from the StructVector's children automatically
- Avoid storing struct columns as json in tables read via Arrow
- Validate nested field counts/types during schema negotiation
When it happens
Trigger: Calling assignBlockFromStructVector (directly or via assignBlockFromValueVector) with a non-RowType, e.g. an array or map column receiving a StructVector, or a struct vector paired with a scalar type.
Common situations: Arrow schema has struct fields but the Presto table was declared with json or a flat type; nested type derivation bugs where child types leak to the parent; schema evolution adding a struct where a scalar existed before.
Related errors
- ELASTICSEARCH_TYPE_MISMATCH
- Invalid row block:
- Type must be a DecimalType for DecimalVector
- Expected TimestampType but got {type.getClass().getName()}
- Expected VarcharType but got {type.getClass().getName()}
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/aeda3bcd922982b2.
Report an issue: GitHub.