apache/iceberg · error · UnsupportedOperationException

Unsupported element type for Array or Map: %s

Error message

Unsupported element type for Array or Map: %s

What it means

VariantRowDataWrapper.elementValue converts a Variant element (inside an ARRAY or MAP) into Flink data according to the declared Flink LogicalType. The switch handles primitives, decimal, string, timestamps, binary, arrays, maps and rows; any other LogicalTypeRoot (e.g. DATE, TIME, INTERVAL, MULTISET) is unsupported and throws UnsupportedOperationException with the element type formatted in the message.

Source

Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/data/VariantRowDataWrapper.java:208

      case BOOLEAN -> variant.getBoolean();
      case TINYINT -> variant.getByte();
      case SMALLINT -> variant.getShort();
      case INTEGER -> intValue(variant);
      case BIGINT -> longValue(variant);
      case FLOAT -> variant.getFloat();
      case DOUBLE -> doubleValue(variant);
      case DECIMAL -> decimalDataValue(variant, (DecimalType) elementType);
      case CHAR, VARCHAR -> StringData.fromString(variant.getString());
      case TIMESTAMP_WITHOUT_TIME_ZONE ->
          timestampValue(variant, ((TimestampType) elementType).getPrecision());
      case TIMESTAMP_WITH_LOCAL_TIME_ZONE ->
          timestampValue(variant, ((LocalZonedTimestampType) elementType).getPrecision());
      case BINARY, VARBINARY -> variant.getBytes();
      case ARRAY -> arrayDataValue(variant, ((ArrayType) elementType).getElementType());
      case MAP -> mapDataValue(variant, (MapType) elementType);
      case ROW -> new VariantRowDataWrapper((RowType) elementType).wrap(variant);
      default ->
          throw new UnsupportedOperationException(
              String.format("Unsupported element type for Array or Map: %s", elementType));
    };
  }

  private static MapData mapDataValue(Variant variant, MapType mapType) {
    if (isNull(variant)) {
      return null;
    }

    LogicalType keyType = mapType.getKeyType();
    LogicalType valueType = mapType.getValueType();

    Preconditions.checkArgument(
        keyType instanceof VarCharType,
        "Only Map with STRING key type is supported in Variant to RowData conversion");

    Map<Object, Object> mapData = Maps.newHashMap();
    List<String> keys = BinaryVariantAccessorUtils.fieldNames(variant);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Adjust the declared RowType so array element / map value types are among the supported set (primitives, decimal, string, timestamp, binary, array, map, row).
  2. Convert unsupported element types (e.g. DATE, TIME) upstream — e.g. read them as string or as their epoch representations.
  3. Upgrade iceberg-flink if a newer version added support for the logical type named in the message.
  4. Filter out or cast the offending nested field in the query before it reaches the variant wrapper.

Example fix

// before
// rowType declares element type DATE() for a variant array
RowData row = new VariantRowDataWrapper(rowType).wrap(variant);
ArrayData arr = row.getArray(pos); // throws

// after
// declare the element as VARCHAR and convert at the sink
RowType fixedType = RowType.of(new VarCharType(), ...);
RowData row = new VariantRowDataWrapper(fixedType).wrap(variant);
StringData dateStr = row.getArray(pos).getString(0); // "2026-09-11"
Defensive patterns

Strategy: validation

Validate before calling

Set<LogicalTypeRoot> supported = Set.of(LogicalTypeRoot.NULL, LogicalTypeRoot.BOOLEAN,
    LogicalTypeRoot.TINYINT, LogicalTypeRoot.SMALLINT, LogicalTypeRoot.INTEGER, LogicalTypeRoot.BIGINT,
    LogicalTypeRoot.FLOAT, LogicalTypeRoot.DOUBLE, LogicalTypeRoot.DECIMAL, LogicalTypeRoot.CHAR,
    LogicalTypeRoot.VARCHAR, LogicalTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE,
    LogicalTypeRoot.TIMESTAMP_WITH_LOCAL_TIME_ZONE, LogicalTypeRoot.BINARY, LogicalTypeRoot.VARBINARY,
    LogicalTypeRoot.ARRAY, LogicalTypeRoot.MAP, LogicalTypeRoot.ROW);
LogicalTypeRoot root = elemType.getTypeRoot();
Preconditions.checkArgument(supported.contains(root),
    "Element type %s unsupported in Variant array/map", elemType);

Type guard

boolean isVariantElementSupported(LogicalType t) {
  switch (t.getTypeRoot()) {
    case DATE:
    case TIME_WITHOUT_TIME_ZONE:
    case INTERVAL_YEAR_MONTH:
    case INTERVAL_DAY_TIME:
      return false;
    default:
      return true;
  }
}

Try / catch

try {
  ArrayData arr = wrapper.getArray(pos);
} catch (UnsupportedOperationException e) {
  if (e.getMessage().startsWith("Unsupported element type for Array or Map:")) {
    log.error("Variant collection element type not supported: {}", e.getMessage());
    throw new UnsupportedColumnTypeException(e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Reading an Iceberg variant column through VariantRowDataWrapper where an array element type or map value type is declared as a Flink type outside the supported set — e.g. a variant array of DATE or TIME values, or a map with non-string key routed to elementValue, in VariantRowDataWrapper.getArray/getMap.

Common situations: Declaring a Flink schema for a variant column whose nested array/map element types use DATE, TIME, or other logical types the wrapper doesn't map; schema evolution adding new element types to variant collections; engine version differences in which Flink types a variant can surface as.

Related errors


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