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

  1. Override variant(Types.VariantType variant) in the visitor subclass to return an appropriate value.
  2. Remove variant columns from the schema before visiting if variants are unsupported.
  3. Migrate off the deprecated visitor hook to the non-deprecated variant(Types.VariantType) method.
  4. 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

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


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