apache/iceberg · error · UnsupportedOperationException
Avro format doesn't support non-string as key type of map. T
Error message
Avro format doesn't support non-string as key type of map. The key type is: <keyType.asSummaryString()>
What it means
extractValueTypeToAvroMap converts a Flink MAP/MULTISET value type for Avro. Avro maps require string keys, so any key type not in CHARACTER_STRING family is rejected with UnsupportedOperationException.
Source
Thrown at flink/v1.20/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)
Solutions
- Cast map keys to STRING before conversion: MAP_CAST via SQL `MAP_FROM_ENTRIES` or rebuild the map with CAST(key AS STRING).
- Restructure the data as an ARRAY<ROW<key,value>> if non-string keys are required.
- Use a non-Avro serialization format (e.g. Avro with schema adaptation via a custom converter) if string keys are impossible.
Example fix
// before: MAP<INT, STRING> fails MapType t = new MapType(new IntType(), new StringType()); // after: string keys MapType t = new MapType(new StringType(), new StringType()); // SQL: SELECT MAP(key_str, val) FROM (SELECT CAST(k AS STRING) AS key_str, v AS val FROM m),
Defensive patterns
Strategy: validation
Validate before calling
// verify map key type is string-like before conversion
LogicalType keyType = type instanceof MapType
? ((MapType) type).getKeyType()
: ((MultisetType) type).getElementType();
if (!keyType.is(LogicalTypeFamily.CHARACTER_STRING)) {
throw new IllegalArgumentException("Map keys must be string-like for Avro: " + keyType);
} Type guard
boolean hasStringMapKey(LogicalType t) {
LogicalType k = t instanceof MapType
? ((MapType) t).getKeyType()
: t instanceof MultisetType ? ((MultisetType) t).getElementType() : null;
return k != null && k.is(LogicalTypeFamily.CHARACTER_STRING);
} Try / catch
try {
schema = AvroSchemaConverter.convertToSchema(mapType);
} catch (UnsupportedOperationException e) {
// convert keys to STRING upstream or use array-of-row representation
schema = AvroSchemaConverter.convertToSchema(stringKeyedEquivalent);
} Prevention
- Use STRING keys in map/multiset columns intended for Avro output
- Cast keys to STRING in SQL views feeding the sink
- Model non-string keyed data as ARRAY<ROW<k,v>> instead of MAP
When it happens
Trigger: Calling extractValueTypeToAvroMap via convertToSchema with a MapType whose key type is not CHAR/VARCHAR/STRING (e.g. MAP<INT,STRING>), or a MultisetType whose element type is non-string.
Common situations: Flink tables with map columns keyed by integers or timestamps (common in aggregation pipelines like MAP<INT, BIGINT> counts) being written through the Avro format.
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
- Unsupported type: ${primitive}
- Unsupported Avro type '${schema.getType()}'.
- Unsupported to derive Schema for type: <logicalType>
- Unsupported type: %s
- Unsupported type: ${primitive}
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/48c9cec8c6129c9c.
Report an issue: GitHub.