apache/iceberg · error · UnsupportedOperationException

Cannot convert type

Error message

Cannot convert type: ${data.getClass().getName()}

What it means

RecordConverter.convert(Object, SchemaUpdate.Consumer) only accepts Kafka Connect Struct or Map values representing the top-level record. Any other Java type (e.g. primitives, lists, raw strings) cannot represent an Iceberg table row, so it throws UnsupportedOperationException naming the actual value class.

Solutions

  1. Ensure the Kafka record value is deserialized into a Connect Struct (set an appropriate value converter, e.g. JsonSchemaConverter with schema, or a schema-registry-backed converter).
  2. Wrap the raw value in a Map (map of field name -> value) so it goes down the convertStructValue path.
  3. Catch UnsupportedOperationException at the record level and route the record to a DLQ instead of failing the task.

Example fix

// before
Record r = converter.convert(record.value(), consumer); // value is a String
// after
Map<String, Object> wrapped = Collections.singletonMap("payload", record.value());
Record r = converter.convert(wrapped, consumer);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(value instanceof Struct) && !(value instanceof Map)) {
  throw new IllegalArgumentException("Top-level record must be Struct or Map, got " + value.getClass().getName());
}

Type guard

boolean isConvertible(Object v) {
  return v instanceof Struct || v instanceof Map;
}

Try / catch

try {
  Record r = converter.convert(value, consumer);
} catch (UnsupportedOperationException e) {
  log.error("Unsupported record value type", e);
  sendToDlq(record, e);
}

Prevention

When it happens

Trigger: Calling RecordConverter.convert with a value that is neither org.apache.kafka.connect.data.Struct nor java.util.Map, e.g. convert("some string", consumer), convert(List.of(1,2), consumer), or passing a numeric/byte[] payload.

Common situations: Kafka Connect record values that were not wrapped in a struct — plain JSON scalars/arrays from topics ingested via the Iceberg sink, or custom users of the connector API passing raw values instead of structured records.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/8f81f1b4393d2159. Report an issue: GitHub.

Appendix: source

Thrown at kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java:118

  private final NameMapping nameMapping;
  private final IcebergSinkConfig config;
  private final Map<Integer, Map<String, NestedField>> structNameMap = Maps.newHashMap();

  RecordConverter(Table table, IcebergSinkConfig config) {
    this.tableSchema = table.schema();
    this.nameMapping = createNameMapping(table);
    this.config = config;
  }

  Record convert(Object data) {
    return convert(data, null);
  }

  Record convert(Object data, SchemaUpdate.Consumer schemaUpdateConsumer) {
    if (data instanceof Struct || data instanceof Map) {
      return convertStructValue(data, tableSchema.asStruct(), -1, schemaUpdateConsumer);
    }
    throw new UnsupportedOperationException("Cannot convert type: " + data.getClass().getName());
  }

  private NameMapping createNameMapping(Table table) {
    String nameMappingString = table.properties().get(TableProperties.DEFAULT_NAME_MAPPING);
    return nameMappingString != null ? NameMappingParser.fromJson(nameMappingString) : null;
  }

  private Object convertValue(
      Object value, Type type, int fieldId, SchemaUpdate.Consumer schemaUpdateConsumer) {
    if (value == null) {
      return null;
    }
    switch (type.typeId()) {
      case STRUCT:
        return convertStructValue(value, type.asStructType(), fieldId, schemaUpdateConsumer);
      case LIST:
        return convertListValue(value, type.asListType(), schemaUpdateConsumer);
      case MAP:

View on GitHub (pinned to 86d9c8fc54)