apache/iceberg · error · UnsupportedOperationException

Not a supported type: ${targetType}

Error message

Not a supported type: ${targetType}

What it means

DataConverter.get() dispatches on the root Flink LogicalType of the source/target pair and only supports ROW, ARRAY, and MAP roots when building converters. Any other top-level type (or an unhandled case) falls into the default branch and throws UnsupportedOperationException naming the offending type. Row-level primitive types are handled at the field level elsewhere, so hitting this means an unexpected root type reached the converter factory.

Source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/sink/dynamic/DataConverter.java:127

        };
      case TIMESTAMP_WITHOUT_TIME_ZONE:
        return object -> {
          if (object instanceof Integer) {
            LocalDateTime dateTime =
                LocalDateTime.of(LocalDate.ofEpochDay((Integer) object), LocalTime.MIN);
            return TimestampData.fromLocalDateTime(dateTime);
          } else {
            return object;
          }
        };
      case ROW:
        return new RowDataConverter((RowType) sourceType, (RowType) targetType);
      case ARRAY:
        return new ArrayConverter((ArrayType) sourceType, (ArrayType) targetType);
      case MAP:
        return new MapConverter((MapType) sourceType, (MapType) targetType);
      default:
        throw new UnsupportedOperationException("Not a supported type: " + targetType);
    }
  }

  static DataConverter nullable(DataConverter converter) {
    return value -> value == null ? null : converter.convert(value);
  }

  class RowDataConverter implements DataConverter {
    private final RowData.FieldGetter[] fieldGetters;
    private final DataConverter[] dataConverters;

    RowDataConverter(RowType sourceType, RowType targetType) {
      this.fieldGetters = new RowData.FieldGetter[targetType.getFields().size()];
      this.dataConverters = new DataConverter[targetType.getFields().size()];

      for (int i = 0; i < targetType.getFields().size(); i++) {
        RowData.FieldGetter fieldGetter;
        DataConverter dataConverter;

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure the types passed to DataConverter.get() are RowType-based (full table rows), not bare primitive types
  2. Add a case to the switch in DataConverter.get() if the new root type genuinely needs support
  3. Log/inspect the targetType value in the message to identify which unexpected type is flowing in

Example fix

// before
DataConverter.get(rowDataType, intType); // throws
// after
DataConverter.get(sourceRowType, targetRowType);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(sourceType instanceof RowType)) {
  throw new IllegalArgumentException("Expected RowType root, got: " + sourceType);
}

Type guard

boolean isSupportedRoot(LogicalType t) {
  switch (t.getTypeRoot()) {
    case ROW:
    case ARRAY:
    case MAP:
      return true;
    default:
      return false;
  }
}

Try / catch

try {
  converter = DataConverter.get(sourceType, targetType);
} catch (UnsupportedOperationException e) {
  // handle unsupported root type: log targetType and fall back / fail fast
}

Prevention

When it happens

Trigger: Calling DataConverter.get(sourceType, targetType) with a root LogicalType other than ROW, ARRAY, or MAP (e.g. a bare IntType, VarCharType, or an unsupported composite type).

Common situations: A table schema change reduced the row to something the dynamic sink's converter dispatch does not handle; an upstream refactor passes a flattened column type instead of a RowType; a new Flink type family not yet covered by the switch.

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/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/e9b4073c1bdcb3c0. Report an issue: GitHub.