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
- Change the map key type to STRING/VARCHAR in the table schema.
- Cast keys to STRING before conversion, e.g. MAP_CAST: CAST(map AS MAP<STRING, DOUBLE>).
- Re-express the map as an ARRAY<ROW<key,value>> which Avro can represent with non-string keys.
- 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
- Design schemas with STRING-keyed maps when Avro serialization is in play
- Use ARRAY<ROW<key,value>> for non-string keys
- Validate RowTypes with AvroSchemaConverter early in the pipeline
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
- Avro does not support TIME type with precision: " +…
- Avro does not support TIME type with precision
- Avro does not support TIMESTAMP type with precision: " +…
- Avro format doesn't support non-string as key type of map…
- Unsupported to derive Schema for type
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)