{"record":{"id":"fb3860c588f6b333","repo":"apache/seatunnel","slug":"row-type-requires-non-empty-field-names-and-types","errorCode":null,"errorMessage":"ROW type requires non-empty field names and types with equal length","messagePattern":"ROW type requires non-empty field names and types with equal length","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":105,"sourceCode":"                return \"binary\";\n            case DATE:\n                return \"date\";\n            case TIME:\n                return \"string\";\n            case TIMESTAMP:\n                return \"timestamp\";\n            case ROW:\n                if (seaTunnelType instanceof org.apache.seatunnel.api.table.type.SeaTunnelRowType) {\n                    org.apache.seatunnel.api.table.type.SeaTunnelRowType rowType =\n                            (org.apache.seatunnel.api.table.type.SeaTunnelRowType) seaTunnelType;\n                    String[] fieldNames = rowType.getFieldNames();\n                    org.apache.seatunnel.api.table.type.SeaTunnelDataType<?>[] fieldTypes =\n                            rowType.getFieldTypes();\n                    if (fieldNames == null\n                            || 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) {","sourceCodeStart":87,"sourceCodeEnd":123,"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#L87-L123","documentation":"In HiveTypeConvertor.seatunnelToHiveType, when converting a SeaTunnel ROW type to a Hive struct type, the row's field names and field types must both be present, non-empty, and of equal length. This guard throws UnsupportedOperationException when the row type is structurally invalid (null/empty names, null types, or a length mismatch).","triggerScenarios":"Recursively converting a SeaTunnelRowType whose getFieldNames() or getFieldTypes() is null, whose fieldNames array is empty, or whose names/types arrays have different lengths — e.g. a row type constructed manually with mismatched arrays or an empty row type.","commonSituations":"Building a SeaTunnelRowType with new String[0] fields; programmatic catalog code that fills names but forgets types; a schema assembled from config where the ROW field count drifted from the type count.","solutions":["Construct the SeaTunnelRowType with equal-length, non-empty fieldNames and fieldTypes arrays.","Validate the row type (names != null && types != null && names.length == types.length && names.length > 0) before converting.","If the nested row is intentionally empty, replace it with a nullable/void field instead of an empty struct."],"exampleFix":"// before\nSeaTunnelRowType bad = new SeaTunnelRowType(new String[0], new SeaTunnelDataType<?>[0]);\n// after\nSeaTunnelRowType good = new SeaTunnelRowType(\n    new String[]{\"id\", \"name\"},\n    new SeaTunnelDataType<?>[]{BasicType.LONG_TYPE, BasicType.STRING_TYPE});","handlingStrategy":"validation","validationCode":"static void validateRowType(SeaTunnelRowType t) {\n    if (t.getFieldNames() == null || t.getFieldTypes() == null\n        || t.getFieldNames().length == 0\n        || t.getFieldNames().length != t.getFieldTypes().length) {\n        throw new IllegalArgumentException(\"Row type has invalid names/types arrays\");\n    }\n}","typeGuard":"static boolean isValidRowType(SeaTunnelDataType<?> t) {\n    return t instanceof SeaTunnelRowType\n        && ((SeaTunnelRowType) t).getFieldNames() != null\n        && ((SeaTunnelRowType) t).getFieldTypes() != null\n        && ((SeaTunnelRowType) t).getFieldNames().length > 0\n        && ((SeaTunnelRowType) t).getFieldNames().length == ((SeaTunnelRowType) t).getFieldTypes().length;\n}","tryCatchPattern":"try {\n    String hiveType = HiveTypeConvertor.seatunnelToHiveType(rowType);\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().contains(\"ROW type requires\")) {\n        // log the offending nested row type definition\n    }\n    throw e;\n}","preventionTips":["Build row types via helpers/constructors that pair names and types in one call.","Unit-test catalog schema construction including nested ROW fields.","Never construct a SeaTunnelRowType with empty arrays for struct columns."],"tags":["hive","type-conversion","row-type","schema"],"backgroundTag":"schema-validation-failed","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"}