apache/seatunnel · error · UnsupportedOperationException

ROW type requires non-empty field names and types

Error message

ROW type requires non-empty field names and types

What it means

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.

Source

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

                            || 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) {
                    org.apache.seatunnel.api.table.type.ArrayType<?, ?> arrayType =
                            (org.apache.seatunnel.api.table.type.ArrayType<?, ?>) seaTunnelType;
                    org.apache.seatunnel.api.table.type.SeaTunnelDataType<?> elementType =
                            arrayType.getElementType();
                    if (elementType == null) {
                        throw new UnsupportedOperationException("ARRAY type requires element type");
                    }
                    return "array<" + seatunnelToHiveType(elementType) + ">";
                }
                throw new UnsupportedOperationException("ARRAY type requires element type");
            case MAP:
                if (seaTunnelType instanceof org.apache.seatunnel.api.table.type.MapType) {
                    org.apache.seatunnel.api.table.type.MapType<?, ?> mapType =
                            (org.apache.seatunnel.api.table.type.MapType<?, ?>) seaTunnelType;
                    org.apache.seatunnel.api.table.type.SeaTunnelDataType<?> keyType =

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Ensure the type passed is an instance of SeaTunnelRowType so the struct branch executes.
  2. If wrapping a row type in a custom class, unwrap to SeaTunnelRowType before conversion.
  3. Update the converter to handle the custom ROW implementation if it must be supported.

Example fix

// before
SeaTunnelDataType<?> t = myCustomRowWrapper; // sqlType=ROW, not SeaTunnelRowType
// after
SeaTunnelDataType<?> t = myCustomRowWrapper.getRowType(); // actual SeaTunnelRowType
Defensive patterns

Strategy: type-guard

Validate before calling

if (type.getSqlType() == SqlType.ROW && !(type instanceof SeaTunnelRowType)) {
    throw new IllegalArgumentException("ROW sqlType requires SeaTunnelRowType instance");
}

Type guard

static boolean isConcreteRowType(SeaTunnelDataType<?> t) {
    return t instanceof SeaTunnelRowType;
}

Try / catch

try {
    String hiveType = HiveTypeConvertor.seatunnelToHiveType(type);
} catch (UnsupportedOperationException e) {
    if (e.getMessage().equals("ROW type requires non-empty field names and types")) {
        // unwrap or convert the custom ROW implementation first
    }
    throw e;
}

Prevention

When it happens

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

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

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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