apache/iceberg · error · UnsupportedOperationException

Avro format doesn't support non-string as key type of map…

Error message

Avro format doesn't support non-string as key type of map. " + "The key type is: " + keyType.asSummaryString()

What it means

Avro maps are required to have string keys, so when deriving the value type for a Flink MAP/MULTISET, extractValueTypeToAvroMap rejects any key type outside the CHARACTER_STRING family with UnsupportedOperationException. This is enforced by the Avro spec, not Iceberg.

Solutions

  1. Change the map key type to STRING/VARCHAR in the table schema.
  2. Cast keys to STRING before conversion, e.g. MAP_CAST: CAST(map AS MAP<STRING, DOUBLE>).
  3. Re-express the map as an ARRAY<ROW<key,value>> which Avro can represent with non-string keys.
  4. Use MULTISET<STRING> instead of MULTISET<non-string> where possible.

Example fix

// before
DataTypes.MAP(DataTypes.INT(), DataTypes.DOUBLE())
// after
DataTypes.MAP(DataTypes.STRING(), DataTypes.DOUBLE())
Defensive patterns

Strategy: validation

Validate before calling

if (type instanceof MapType) {
  LogicalType key = ((MapType) type).getKeyType();
  Preconditions.checkArgument(key.is(LogicalTypeFamily.CHARACTER_STRING),
      "Map key must be STRING for Avro, got " + key.asSummaryString());
} else if (type instanceof MultisetType) {
  LogicalType el = ((MultisetType) type).getElementType();
  Preconditions.checkArgument(el.is(LogicalTypeFamily.CHARACTER_STRING),
      "Multiset element key must be STRING for Avro, got " + el.asSummaryString());
}

Type guard

boolean hasStringMapKeys(LogicalType t) {
  if (t instanceof MapType m) return m.getKeyType().is(LogicalTypeFamily.CHARACTER_STRING);
  if (t instanceof MultisetType ms) return ms.getElementType().is(LogicalTypeFamily.CHARACTER_STRING);
  return true;
}

Try / catch

try {
  Schema s = AvroSchemaConverter.convertToSchema(rowType);
} catch (UnsupportedOperationException e) {
  // cast map keys to STRING or re-model as ARRAY<ROW<K,V>> and retry
}

Prevention

When it happens

Trigger: Converting a RowType containing MAP<INT, ...>, MAP<LONG, ...>, MULTISET<INT>, or any non-CHAR/VARCHAR key type through AvroSchemaConverter (extractValueTypeToAvroMap is called from the map case).

Common situations: Flink tables using integer-keyed maps (e.g. MAP<INT, DOUBLE> aggregations or MULTISET counts of non-string elements) run through Avro-based serialization.

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/f535a1058776122f. Report an issue: GitHub.

Appendix: source

Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/formats/avro/typeutils/AvroSchemaConverter.java:611

        throw new UnsupportedOperationException(
            "Unsupported to derive Schema for type: " + logicalType);
    }
  }

  public static LogicalType extractValueTypeToAvroMap(LogicalType type) {
    LogicalType keyType;
    LogicalType valueType;
    if (type instanceof MapType) {
      MapType mapType = (MapType) type;
      keyType = mapType.getKeyType();
      valueType = mapType.getValueType();
    } else {
      MultisetType multisetType = (MultisetType) type;
      keyType = multisetType.getElementType();
      valueType = new IntType();
    }
    if (!keyType.is(LogicalTypeFamily.CHARACTER_STRING)) {
      throw new UnsupportedOperationException(
          "Avro format doesn't support non-string as key type of map. "
              + "The key type is: "
              + keyType.asSummaryString());
    }
    return valueType;
  }

  /** Returns schema with nullable true. */
  private static Schema nullableSchema(Schema schema) {
    return schema.isNullable()
        ? schema
        : Schema.createUnion(SchemaBuilder.builder().nullType(), schema);
  }
}

View on GitHub (pinned to 86d9c8fc54)