{"record":{"id":"aeda3bcd922982b2","repo":"prestodb/presto","slug":"type-must-be-a-rowtype-for-structvector","errorCode":null,"errorMessage":"Type must be a RowType for StructVector","messagePattern":"Type must be a RowType for StructVector","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-common-arrow/src/main/java/com/facebook/plugin/arrow/ArrowBlockBuilder.java","lineNumber":752,"sourceCode":"                builder.appendNull();\n            }\n            else {\n                BlockBuilder entryBuilder = builder.beginBlockEntry();\n                int entryStart = vector.getElementStartIndex(i);\n                int entryEnd = vector.getElementEndIndex(i);\n                for (int entryIndex = entryStart; entryIndex < entryEnd; entryIndex++) {\n                    assignBlockFromValueVector(keyVector, mapType.getKeyType(), entryBuilder, entryIndex, entryIndex + 1);\n                    assignBlockFromValueVector(valueVector, mapType.getValueType(), entryBuilder, entryIndex, entryIndex + 1);\n                }\n                builder.closeEntry();\n            }\n        }\n    }\n\n    public void assignBlockFromStructVector(StructVector vector, Type type, BlockBuilder builder, int startIndex, int endIndex)\n    {\n        if (!(type instanceof RowType)) {\n            throw new IllegalArgumentException(\"Type must be a RowType for StructVector\");\n        }\n\n        RowType rowType = (RowType) type;\n\n        for (int i = startIndex; i < endIndex; i++) {\n            if (vector.isNull(i)) {\n                builder.appendNull();\n            }\n            else {\n                BlockBuilder childBuilder = builder.beginBlockEntry();\n                List<Type> childTypes = rowType.getTypeParameters();\n                for (int childIndex = 0; childIndex < childTypes.size(); childIndex++) {\n                    Type childType = childTypes.get(childIndex);\n                    ValueVector childVector = vector.getChildByOrdinal(childIndex);\n                    assignBlockFromValueVector(childVector, childType, childBuilder, i, i + 1);\n                }\n                builder.closeEntry();\n            }","sourceCodeStart":734,"sourceCodeEnd":770,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common-arrow/src/main/java/com/facebook/plugin/arrow/ArrowBlockBuilder.java#L734-L770","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nassignBlockFromStructVector(structVector, VarcharType.VARCHAR, builder, start, end);\n// after\nassignBlockFromStructVector(structVector, RowType.from(fieldNames, fieldTypes), builder, start, end);","handlingStrategy":"type-guard","validationCode":"if (!(columnType instanceof RowType)) {\n    throw new IllegalStateException(\"Column '\" + name + \"' must be RowType to receive StructVector, got \" + columnType);\n}","typeGuard":"boolean isRowColumn(Type type) {\n    return type instanceof RowType;\n}","tryCatchPattern":"try {\n    builder.assignBlockFromStructVector(vector, type, blockBuilder, start, end);\n} catch (IllegalArgumentException e) {\n    if (!e.getMessage().contains(\"RowType for StructVector\")) throw e;\n    // re-derive RowType from struct children and retry\n}","preventionTips":["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"],"tags":["arrow","type-mismatch","struct","row"],"backgroundTag":"arrow-vector-type-mismatch","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}