apache/seatunnel · error · UnsupportedOperationException

ROW type requires non-empty field names and types with equal

Error message

ROW type requires non-empty field names and types with equal length

What it means

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).

Source

Thrown at seatunnel-connectors-v2/connector-hive/src/main/java/org/apache/seatunnel/connectors/seatunnel/hive/utils/HiveTypeConvertor.java:105

                return "binary";
            case DATE:
                return "date";
            case TIME:
                return "string";
            case TIMESTAMP:
                return "timestamp";
            case ROW:
                if (seaTunnelType instanceof org.apache.seatunnel.api.table.type.SeaTunnelRowType) {
                    org.apache.seatunnel.api.table.type.SeaTunnelRowType rowType =
                            (org.apache.seatunnel.api.table.type.SeaTunnelRowType) seaTunnelType;
                    String[] fieldNames = rowType.getFieldNames();
                    org.apache.seatunnel.api.table.type.SeaTunnelDataType<?>[] fieldTypes =
                            rowType.getFieldTypes();
                    if (fieldNames == null
                            || fieldTypes == null
                            || fieldNames.length == 0
                            || fieldNames.length != fieldTypes.length) {
                        throw new UnsupportedOperationException(
                                "ROW type requires non-empty field names and types with equal length");
                    }
                    StringBuilder sb = new StringBuilder("struct<");
                    for (int i = 0; i < fieldNames.length; i++) {
                        if (i > 0) {
                            sb.append(',');
                        }
                        sb.append(fieldNames[i])
                                .append(':')
                                .append(seatunnelToHiveType(fieldTypes[i]));
                    }
                    sb.append('>');
                    return sb.toString();
                }
                throw new UnsupportedOperationException(
                        "ROW type requires non-empty field names and types");
            case ARRAY:
                if (seaTunnelType instanceof org.apache.seatunnel.api.table.type.ArrayType) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Construct the SeaTunnelRowType with equal-length, non-empty fieldNames and fieldTypes arrays.
  2. Validate the row type (names != null && types != null && names.length == types.length && names.length > 0) before converting.
  3. If the nested row is intentionally empty, replace it with a nullable/void field instead of an empty struct.

Example fix

// before
SeaTunnelRowType bad = new SeaTunnelRowType(new String[0], new SeaTunnelDataType<?>[0]);
// after
SeaTunnelRowType good = new SeaTunnelRowType(
    new String[]{"id", "name"},
    new SeaTunnelDataType<?>[]{BasicType.LONG_TYPE, BasicType.STRING_TYPE});
Defensive patterns

Strategy: validation

Validate before calling

static void validateRowType(SeaTunnelRowType t) {
    if (t.getFieldNames() == null || t.getFieldTypes() == null
        || t.getFieldNames().length == 0
        || t.getFieldNames().length != t.getFieldTypes().length) {
        throw new IllegalArgumentException("Row type has invalid names/types arrays");
    }
}

Type guard

static boolean isValidRowType(SeaTunnelDataType<?> t) {
    return t instanceof SeaTunnelRowType
        && ((SeaTunnelRowType) t).getFieldNames() != null
        && ((SeaTunnelRowType) t).getFieldTypes() != null
        && ((SeaTunnelRowType) t).getFieldNames().length > 0
        && ((SeaTunnelRowType) t).getFieldNames().length == ((SeaTunnelRowType) t).getFieldTypes().length;
}

Try / catch

try {
    String hiveType = HiveTypeConvertor.seatunnelToHiveType(rowType);
} catch (UnsupportedOperationException e) {
    if (e.getMessage().contains("ROW type requires")) {
        // log the offending nested row type definition
    }
    throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/fb3860c588f6b333. Report an issue: GitHub.