{"record":{"id":"398444b17902d932","repo":"apache/seatunnel","slug":"row-type-requires-non-empty-field-names-and-types-398444","errorCode":null,"errorMessage":"ROW type requires non-empty field names and types","messagePattern":"ROW type requires non-empty field names and types","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-hive/src/main/java/org/apache/seatunnel/connectors/seatunnel/hive/utils/HiveTypeConvertor.java","lineNumber":120,"sourceCode":"                            || fieldTypes == null\n                            || fieldNames.length == 0\n                            || fieldNames.length != fieldTypes.length) {\n                        throw new UnsupportedOperationException(\n                                \"ROW type requires non-empty field names and types with equal length\");\n                    }\n                    StringBuilder sb = new StringBuilder(\"struct<\");\n                    for (int i = 0; i < fieldNames.length; i++) {\n                        if (i > 0) {\n                            sb.append(',');\n                        }\n                        sb.append(fieldNames[i])\n                                .append(':')\n                                .append(seatunnelToHiveType(fieldTypes[i]));\n                    }\n                    sb.append('>');\n                    return sb.toString();\n                }\n                throw new UnsupportedOperationException(\n                        \"ROW type requires non-empty field names and types\");\n            case ARRAY:\n                if (seaTunnelType instanceof org.apache.seatunnel.api.table.type.ArrayType) {\n                    org.apache.seatunnel.api.table.type.ArrayType<?, ?> arrayType =\n                            (org.apache.seatunnel.api.table.type.ArrayType<?, ?>) seaTunnelType;\n                    org.apache.seatunnel.api.table.type.SeaTunnelDataType<?> elementType =\n                            arrayType.getElementType();\n                    if (elementType == null) {\n                        throw new UnsupportedOperationException(\"ARRAY type requires element type\");\n                    }\n                    return \"array<\" + seatunnelToHiveType(elementType) + \">\";\n                }\n                throw new UnsupportedOperationException(\"ARRAY type requires element type\");\n            case MAP:\n                if (seaTunnelType instanceof org.apache.seatunnel.api.table.type.MapType) {\n                    org.apache.seatunnel.api.table.type.MapType<?, ?> mapType =\n                            (org.apache.seatunnel.api.table.type.MapType<?, ?>) seaTunnelType;\n                    org.apache.seatunnel.api.table.type.SeaTunnelDataType<?> keyType =","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-hive/src/main/java/org/apache/seatunnel/connectors/seatunnel/hive/utils/HiveTypeConvertor.java#L102-L138","documentation":"Fallback guard in HiveTypeConvertor.seatunnelToHiveType: when the SQLType is ROW but the passed SeaTunnelDataType is not an instance of SeaTunnelRowType (or the struct-building path was not reached), the converter cannot express it as a Hive struct and throws UnsupportedOperationException.","triggerScenarios":"Calling seatunnelToHiveType with a type whose getSqlType() is ROW but whose runtime class is not org.apache.seatunnel.api.table.type.SeaTunnelRowType (or ArrayType/MapType subtype confusion) — e.g. a custom DataType implementation reporting ROW.","commonSituations":"Passing a generic SeaTunnelDataType wrapper instead of a SeaTunnelRowType; a custom catalog returning an exotic ROW-typed implementation; refactored code that changed the row type class but kept SqlType.ROW.","solutions":["Ensure the type passed is an instance of SeaTunnelRowType so the struct branch executes.","If wrapping a row type in a custom class, unwrap to SeaTunnelRowType before conversion.","Update the converter to handle the custom ROW implementation if it must be supported."],"exampleFix":"// before\nSeaTunnelDataType<?> t = myCustomRowWrapper; // sqlType=ROW, not SeaTunnelRowType\n// after\nSeaTunnelDataType<?> t = myCustomRowWrapper.getRowType(); // actual SeaTunnelRowType","handlingStrategy":"type-guard","validationCode":"if (type.getSqlType() == SqlType.ROW && !(type instanceof SeaTunnelRowType)) {\n    throw new IllegalArgumentException(\"ROW sqlType requires SeaTunnelRowType instance\");\n}","typeGuard":"static boolean isConcreteRowType(SeaTunnelDataType<?> t) {\n    return t instanceof SeaTunnelRowType;\n}","tryCatchPattern":"try {\n    String hiveType = HiveTypeConvertor.seatunnelToHiveType(type);\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().equals(\"ROW type requires non-empty field names and types\")) {\n        // unwrap or convert the custom ROW implementation first\n    }\n    throw e;\n}","preventionTips":["Only use SeaTunnelRowType for ROW-typed fields.","Add an instanceof assertion in catalog code that produces schemas.","Keep a single SeaTunnel API version on the classpath."],"tags":["hive","type-conversion","row-type"],"backgroundTag":"unsupported-operation","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}