{"record":{"id":"48c9cec8c6129c9c","repo":"apache/iceberg","slug":"avro-format-doesn-t-support-non-string-as-key-type","errorCode":null,"errorMessage":"Avro format doesn't support non-string as key type of map. The key type is: <keyType.asSummaryString()>","messagePattern":"Avro format doesn't support non-string as key type of map\\. The key type is: <keyType\\.asSummaryString\\(\\)>","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/formats/avro/typeutils/AvroSchemaConverter.java","lineNumber":611,"sourceCode":"        throw new UnsupportedOperationException(\n            \"Unsupported to derive Schema for type: \" + logicalType);\n    }\n  }\n\n  public static LogicalType extractValueTypeToAvroMap(LogicalType type) {\n    LogicalType keyType;\n    LogicalType valueType;\n    if (type instanceof MapType) {\n      MapType mapType = (MapType) type;\n      keyType = mapType.getKeyType();\n      valueType = mapType.getValueType();\n    } else {\n      MultisetType multisetType = (MultisetType) type;\n      keyType = multisetType.getElementType();\n      valueType = new IntType();\n    }\n    if (!keyType.is(LogicalTypeFamily.CHARACTER_STRING)) {\n      throw new UnsupportedOperationException(\n          \"Avro format doesn't support non-string as key type of map. \"\n              + \"The key type is: \"\n              + keyType.asSummaryString());\n    }\n    return valueType;\n  }\n\n  /** Returns schema with nullable true. */\n  private static Schema nullableSchema(Schema schema) {\n    return schema.isNullable()\n        ? schema\n        : Schema.createUnion(SchemaBuilder.builder().nullType(), schema);\n  }\n}\n","sourceCodeStart":593,"sourceCodeEnd":626,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/formats/avro/typeutils/AvroSchemaConverter.java#L593-L626","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: MAP<INT, STRING> fails\nMapType t = new MapType(new IntType(), new StringType());\n\n// after: string keys\nMapType t = new MapType(new StringType(), new StringType());\n// SQL: SELECT MAP(key_str, val) FROM (SELECT CAST(k AS STRING) AS key_str, v AS val FROM m),","handlingStrategy":"validation","validationCode":"// verify map key type is string-like before conversion\nLogicalType keyType = type instanceof MapType\n    ? ((MapType) type).getKeyType()\n    : ((MultisetType) type).getElementType();\nif (!keyType.is(LogicalTypeFamily.CHARACTER_STRING)) {\n    throw new IllegalArgumentException(\"Map keys must be string-like for Avro: \" + keyType);\n}","typeGuard":"boolean hasStringMapKey(LogicalType t) {\n    LogicalType k = t instanceof MapType\n        ? ((MapType) t).getKeyType()\n        : t instanceof MultisetType ? ((MultisetType) t).getElementType() : null;\n    return k != null && k.is(LogicalTypeFamily.CHARACTER_STRING);\n}","tryCatchPattern":"try {\n    schema = AvroSchemaConverter.convertToSchema(mapType);\n} catch (UnsupportedOperationException e) {\n    // convert keys to STRING upstream or use array-of-row representation\n    schema = AvroSchemaConverter.convertToSchema(stringKeyedEquivalent);\n}","preventionTips":["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"],"tags":["avro","flink","map","unsupported-type"],"backgroundTag":"incompatible-source-type","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}