apache/iceberg · error · UnsupportedOperationException
Unsupported type: variant
Error message
Unsupported type: variant
What it means
AvroSchemaVisitor.variant is the hook invoked when the visitor encounters an Iceberg Variant type in an Avro schema. The base implementation throws UnsupportedOperationException because plain Avro has no Variant representation; only visitors that explicitly support variants override this method.
Source
Thrown at core/src/main/java/org/apache/iceberg/avro/AvroSchemaVisitor.java:119
public T record(Schema record, List<String> names, List<T> fields) {
return null;
}
public T union(Schema union, List<T> options) {
return null;
}
public T array(Schema array, T element) {
return null;
}
public T map(Schema map, T value) {
return null;
}
public T variant(Schema variant, T metadataResult, T valueResult) {
throw new UnsupportedOperationException("Unsupported type: variant");
}
public T primitive(Schema primitive) {
return null;
}
}
View on GitHub (pinned to 86d9c8fc54)
Solutions
- Upgrade to an Iceberg version that supports the Variant type and its Avro mapping
- Override variant() in your AvroSchemaVisitor subclass with the appropriate handling for metadata/value results
- Exclude variant columns from the read projection if variants are not needed
- If the engine lacks Variant support, cast/convert the column to a supported type at write time
Example fix
// before: visitor without variant support
new AvroSchemaVisitor<Type>() {
@Override public Type record(Schema rec, List<String> names, List<Type> types) { ... }
@Override public Type primitive(Schema p) { ... }
}
// after: override variant
new AvroSchemaVisitor<Type>() {
@Override public Type record(Schema rec, List<String> names, List<Type> types) { ... }
@Override public Type primitive(Schema p) { ... }
@Override public Type variant(Schema s, Type metadata, Type value) {
return Types.VariantType.get();
}
} Defensive patterns
Strategy: try-catch
Validate before calling
boolean hasVariant = schema.columns().stream()
.anyMatch(f -> f.schema().type() instanceof Types.VariantType);
if (hasVariant && !supportsVariant()) {
throw new IllegalStateException("Reader stack does not support Variant columns");
} Try / catch
try {
return AvroSchemaUtil.convert(avroSchema, tableSchema.asStruct());
} catch (UnsupportedOperationException e) {
if (e.getMessage() != null && e.getMessage().contains("variant")) {
return convertWithoutVariantColumns(avroSchema, tableSchema);
}
throw e;
} Prevention
- Keep Iceberg/engine versions aligned with the table format version in use (Variant requires v3 support)
- Always override variant() in custom AvroSchemaVisitor subclasses when v3 tables are possible
- Project away variant columns if the downstream reader cannot handle them
- Convert variant columns to supported types for older consumers
When it happens
Trigger: Visiting (e.g. via AvroSchemaUtil.convert or a custom AvroSchemaVisitor subclass that does not override variant()) an Avro record structured as an Iceberg Variant (metadata + value fields), typically in Avro files written for a v3 table containing variant columns.
Common situations: Reading Avro files containing Variant columns with a reader stack (reader function/visitor) built before Variant support; custom projection visitors that handle record/map/list/primitives but not variant; engine or library version too old for Variant types.
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
- Unsupported type: variant
- Unsupported type: variant
- Unsupported type: variant
- Cannot coerce value to int:
- Invalid primitive type for decimal:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/f423aef910d56ae4.
Report an issue: GitHub.