apache/iceberg · error · UnsupportedOperationException
Cannot extract value from type
Error message
Cannot extract value from type: ${recordValue.getClass().getName()} What it means
RecordUtils.extractFromRecordValue only supports Kafka Connect Struct and Map record values when resolving a dotted fieldName (e.g. upsert key columns or partition/route columns). Any other type throws UnsupportedOperationException naming the actual class.
Solutions
- Ensure the record value schema is a Struct (use JsonConverter with schemas.enable=true or an SMT like HoistField to wrap primitives into a struct).
- If values are JSON strings, add a transform that parses JSON into a Struct before the sink.
- Change the configured field reference to point at a field that exists in a Struct/Map value.
- Use IcebergSinkConfig route/key settings matching the actual record shape.
Example fix
// before: value schema is int64, config expects 'user.id' "iceberg.route-field": "user.id" // after: wrap primitive into struct via HoistField then reference "transforms.hoist.type": "org.apache.kafka.connect.transforms.HoistField$Value", "transforms.hoist.field": "user"
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(record.value() instanceof Struct) && !(record.value() instanceof Map)) {
throw new DataException("Field extraction requires Struct or Map value");
} Type guard
boolean isExtractable(Object v) {
return v instanceof Struct || v instanceof Map;
} Try / catch
try { return RecordUtils.extractFromRecordValue(value, fieldName); }
catch (UnsupportedOperationException e) { LOG.error("non-struct value: {}", e.getMessage()); throw new RetriableException(e); } Prevention
- Use converters that produce Struct values (schemas.enable=true)
- Wrap primitives with HoistField before the sink
- Validate key/route field paths against the actual value schema
When it happens
Trigger: Configuring iceberg.coordinator.key-field / partition-field / route-field (via the sink's field extraction) while the record value is a raw primitive, byte[], or other non-Struct/non-Map Connect type.
Common situations: Topics with schema-less or primitive values (string/JSON-as-string) paired with a config expecting nested field lookups; converters producing ByteArray/Json schemas for keys.
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
- Cannot convert Number to variant (unknown type)
- Cannot convert to variant
- Unsupported type
- An error occurred closing catalog instance, ignoring...
- An error occurred converting record, topic
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/5535bee8bb3f8dc7.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordUtils.java:58
import org.apache.iceberg.relocated.com.google.common.collect.Sets;
import org.apache.iceberg.relocated.com.google.common.primitives.Ints;
import org.apache.iceberg.types.TypeUtil;
import org.apache.iceberg.types.Types.NestedField;
import org.apache.iceberg.util.PropertyUtil;
import org.apache.kafka.connect.data.Field;
import org.apache.kafka.connect.data.Struct;
class RecordUtils {
@SuppressWarnings("unchecked")
static Object extractFromRecordValue(Object recordValue, String fieldName) {
List<String> fields = Splitter.on('.').splitToList(fieldName);
if (recordValue instanceof Struct) {
return valueFromStruct((Struct) recordValue, fields);
} else if (recordValue instanceof Map) {
return valueFromMap((Map<String, ?>) recordValue, fields);
} else {
throw new UnsupportedOperationException(
"Cannot extract value from type: " + recordValue.getClass().getName());
}
}
private static Object valueFromStruct(Struct parent, List<String> fields) {
Struct struct = parent;
for (int idx = 0; idx < fields.size() - 1; idx++) {
Object value = fieldValueFromStruct(struct, fields.get(idx));
if (value == null) {
return null;
}
Preconditions.checkState(value instanceof Struct, "Expected a struct type");
struct = (Struct) value;
}
return fieldValueFromStruct(struct, fields.get(fields.size() - 1));
}
private static Object fieldValueFromStruct(Struct struct, String fieldName) {View on GitHub (pinned to 86d9c8fc54)