apache/iceberg · error
Unsupported type: variant
Error message
Unsupported type: variant
What it means
This is the deprecated single-arg T variant() hook (deprecated SchemaVisitor in TypeUtil). Visitors that do not override variant(Types.VariantType) get the default implementation, which throws UnsupportedOperationException when the traversal encounters a VariantType node. It exists so old visitor subclasses fail loudly instead of silently mishandling variant columns.
Source
Thrown at api/src/main/java/org/apache/iceberg/types/TypeUtil.java:753
public T list(Types.ListType list, T elementResult) {
return null;
}
public T map(Types.MapType map, T keyResult, T valueResult) {
return null;
}
/**
* @deprecated will be removed in 2.0.0; use {@link #variant(Types.VariantType)} instead.
*/
@Deprecated
public T variant() {
return variant(Types.VariantType.get());
}
public T variant(Types.VariantType variant) {
throw new UnsupportedOperationException("Unsupported type: variant");
}
public T primitive(Type.PrimitiveType primitive) {
return null;
}
}
public static <T> T visit(Schema schema, SchemaVisitor<T> visitor) {
return visitor.schema(schema, visit(schema.asStruct(), visitor));
}
public static <T> T visit(Type type, SchemaVisitor<T> visitor) {
switch (type.typeId()) {
case STRUCT:
Types.StructType struct = type.asNestedType().asStructType();
List<T> results = Lists.newArrayListWithExpectedSize(struct.fields().size());
for (Types.NestedField field : struct.fields()) {
visitor.beforeField(field);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Override variant(Types.VariantType variant) in the visitor subclass to return an appropriate value.
- Remove variant columns from the schema before visiting if variants are unsupported.
- Migrate off the deprecated visitor hook to the non-deprecated variant(Types.VariantType) method.
- Catch UnsupportedOperationException if variants are intentionally unsupported by the visitor.
Example fix
// before
class MyVisitor extends TypeUtil.SchemaVisitor<String> {
// no variant() override -> throws on variant columns
}
// after
class MyVisitor extends TypeUtil.SchemaVisitor<String> {
@Override
public String variant(Types.VariantType variant) {
return Types.VariantType.get().toString();
}
} Defensive patterns
Strategy: try-catch
Validate before calling
boolean hasVariant = schema.columns().stream().anyMatch(Types.NestedField::isVariant);
if (hasVariant) { /* ensure visitor overrides variant() */ } Type guard
boolean visitorHandlesVariants = MyVisitor.class
.getMethod("variant", Types.VariantType.class).getDeclaringClass() != TypeUtil.SchemaVisitor.class; Try / catch
try {
T result = TypeUtil.visit(schema, visitor);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("variant")) { /* strip variant columns or upgrade visitor */ }
throw e;
} Prevention
- Always override variant(Types.VariantType) when subclassing visitors.
- Detect variant columns before traversal and handle them explicitly.
- Update legacy visitors when upgrading Iceberg past variant support.
When it happens
Trigger: Running a custom (or older) TypeUtil.SchemaVisitor subclass that does not override variant(Types.VariantType) against a schema containing a variant column; calling the deprecated variant() hook directly.
Common situations: Custom projection/pruning/rewriting visitors written before the Variant type was introduced; upgrading Iceberg and pointing existing visitors at tables that now contain variant columns; libraries internally using SchemaVisitor on user schemas with variant fields.
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
- Not implemented for variant
- %s does not implement deleteFile
- %s does not implement addFile
- %s does not implement dataSequenceNumber
- %s does not implement removeRows
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/9d58f1922af76019.
Report an issue: GitHub.