apache/iceberg · error · UnsupportedOperationException

Not a supported type: " + flinkVariant.getClass()

Error message

Not a supported type: " + flinkVariant.getClass()

What it means

FlinkVariantShreddingAnalyzer.extractVariantValues converts a Flink Variant from RowData into an Iceberg VariantValue for variant shredding analysis. It only knows how to handle org.apache.flink.types.variant.BinaryVariant (the serialized metadata+value representation). If the RowData.getVariant() call returns a Variant implementation of any other class, the analyzer throws UnsupportedOperationException naming the unexpected class.

Source

Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/data/FlinkVariantShreddingAnalyzer.java:58

  protected List<VariantValue> extractVariantValues(
      List<RowData> bufferedRows, int variantFieldIndex) {
    List<VariantValue> values = Lists.newArrayList();

    for (RowData row : bufferedRows) {
      if (!row.isNullAt(variantFieldIndex)) {
        Variant flinkVariant = row.getVariant(variantFieldIndex);
        if (flinkVariant != null) {
          if (flinkVariant instanceof BinaryVariant binaryVariant) {
            VariantValue variantValue =
                VariantValue.from(
                    VariantMetadata.from(
                        ByteBuffer.wrap(binaryVariant.getMetadata())
                            .order(ByteOrder.LITTLE_ENDIAN)),
                    ByteBuffer.wrap(binaryVariant.getValue()).order(ByteOrder.LITTLE_ENDIAN));

            values.add(variantValue);
          } else {
            throw new UnsupportedOperationException(
                "Not a supported type: " + flinkVariant.getClass());
          }
        }
      }
    }

    return values;
  }

  @Override
  protected int resolveColumnIndex(RowType flinkSchema, String columnName) {
    return flinkSchema.getFieldIndex(columnName);
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure the variant field in the RowData is backed by BinaryVariant (standard little-endian metadata/value encoding) before running shredding analysis.
  2. Check the Flink version used at runtime matches the iceberg-flink module's expected Flink 2.2 Variant API so getVariant() returns BinaryVariant.
  3. If a custom Variant implementation is in play, convert it to bytes (metadata+value) and wrap it in BinaryVariant upstream of the analyzer.
  4. If you control the code, extend the analyzer's else branch to support the extra Variant class explicitly.

Example fix

// before
Variant flinkVariant = row.getVariant(variantFieldIndex);
shreddingAnalyzer.analyze(row);

// after
Variant flinkVariant = row.getVariant(variantFieldIndex);
if (!(flinkVariant instanceof BinaryVariant)) {
  throw new IllegalArgumentException("Variant field must be BinaryVariant, got: " + flinkVariant.getClass());
}
shreddingAnalyzer.analyze(row);
Defensive patterns

Strategy: type-guard

Validate before calling

Variant v = row.getVariant(variantFieldIndex);
if (v != null && !(v instanceof BinaryVariant)) {
  throw new IllegalArgumentException("Variant must be BinaryVariant, got: " + v.getClass());
}

Type guard

boolean isBinaryVariant(Variant v) {
  return v == null || v instanceof BinaryVariant;
}

Try / catch

try {
  analyzer.analyze(rows);
} catch (UnsupportedOperationException e) {
  if (e.getMessage().startsWith("Not a supported type:")) {
    log.error("Variant implementation not supported for shredding", e);
    return fallbackShreddingPlan(rows);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling variant shredding analysis (e.g. via rewrite data files / variant shredding support) on Flink RowData whose variant field is a non-BinaryVariant Variant implementation, i.e. row.getVariant(variantFieldIndex) returns a class other than BinaryVariant.

Common situations: Using a Flink runtime or connector that materializes Variant objects with a different implementation class than the BinaryVariant produced by the standard binary encoding; running a Flink version whose Variant API differs from the one iceberg-flink-runtime 2.2 was built against; custom RowData wrappers returning their own Variant implementations.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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