apache/iceberg · error · IllegalArgumentException
Cannot convert to variant
Error message
Cannot convert to variant: ${value.getClass().getName()} What it means
objectToVariantValue throws this IllegalArgumentException when a value destined for an Iceberg Variant column is of an unrecognized Java type. Supported inputs are primitives, CharSequence, byte arrays/ByteBuffer, BigDecimal, temporal types, Struct, and Map; anything else (or null-typed containers it cannot interpret) fails.
Solutions
- Pre-transform the value into a supported type (String, Number, byte[], Map, Struct) in an SMT
- Log the offending class from the message and add an explicit conversion branch in a RecordConverter subclass
- Fix the producer to emit JSON/Avro values that map to standard Connect types
- If the field is not meant to be a Variant, correct the table schema or field mapping
Example fix
// before value = new com.fasterxml.jackson.databind.JsonNode(...) // unsupported class // after value = jsonNode.toString() // or convert to Map<String,Object> first
Defensive patterns
Strategy: type-guard
Validate before calling
static boolean isVariantCompatible(Object v) {
return v == null || v instanceof Boolean || v instanceof Number || v instanceof CharSequence
|| v instanceof byte[] || v instanceof ByteBuffer || v instanceof java.math.BigDecimal
|| v instanceof java.time.temporal.Temporal || v instanceof Map || v instanceof Struct;
} Type guard
static void requireVariantCompatible(Object v) {
if (v != null && !isVariantCompatible(v)) {
throw new IllegalStateException("Unsupported variant type: " + v.getClass());
}
} Try / catch
try {
converter.convertValue(value, Types.VariantType.get());
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Cannot convert to variant:")) {
log.error("Unsupported variant input class", e);
// fallback: serialize value to JSON string and store as string variant
}
} Prevention
- Restrict SMT outputs to standard Connect types
- Avoid passing framework-specific wrappers (JsonNode, custom Number subclasses)
- Document supported variant input types for producers
- Add contract tests for variant payloads end to end
When it happens
Trigger: A Variant field receives a custom domain object, an array/List not wrapped as expected, or some type produced by an SMT that the converter has no branch for.
Common situations: Custom SMTs output exotic types (e.g. Guava objects, custom Avro wrappers); schema-less JSON arrives as JsonNode-like objects; version upgrade introduced a new Variant conversion path the payload doesn't match.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Cannot convert Number to variant (unknown type)
- Avro writer does not support variant types
- Cannot convert java.util.Date to variant without a…
- Cannot convert map to variant: keys must be non-null…
- Cannot extract value from type
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/b728dd35af49169f.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java:670
ValueArray array = Variants.array();
org.apache.kafka.connect.data.Schema elementSchema =
schema != null ? schema.valueSchema() : null;
for (Object element : collection) {
array.add(objectToVariantValue(element, metadata, elementSchema));
}
return array;
}
if (value instanceof Map<?, ?> map) {
return mapToVariantValue(map, metadata, schema);
}
if (value instanceof Struct struct) {
ShreddedObject object = Variants.object(metadata);
for (Field field : struct.schema().fields()) {
object.put(field.name(), objectToVariantValue(struct.get(field), metadata, field.schema()));
}
return object;
}
throw new IllegalArgumentException("Cannot convert to variant: " + value.getClass().getName());
}
/** Converts a Map to VariantValue; throw IllegalArgumentException if the key is not a string. */
private static VariantValue mapToVariantValue(
Map<?, ?> map, VariantMetadata metadata, org.apache.kafka.connect.data.Schema schema) {
ShreddedObject object = Variants.object(metadata);
org.apache.kafka.connect.data.Schema mapValueSchema =
schema != null ? schema.valueSchema() : null;
map.forEach(
(key, val) -> {
if (key instanceof String keyStr) {
object.put(keyStr, objectToVariantValue(val, metadata, mapValueSchema));
} else {
throw new IllegalArgumentException(
"Cannot convert map to variant: keys must be non-null strings, was: "
+ (key == null ? "null" : key.getClass().getName()));
}
});View on GitHub (pinned to 86d9c8fc54)