{"record":{"id":"f535a1058776122f","repo":"apache/iceberg","slug":"avro-format-doesn-t-support-non-string-as-key-type-f535a1","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/v2.2/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/v2.2/flink/src/main/java/org/apache/iceberg/flink/formats/avro/typeutils/AvroSchemaConverter.java#L593-L626","documentation":"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.","triggerScenarios":"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).","commonSituations":"Flink tables using integer-keyed maps (e.g. MAP<INT, DOUBLE> aggregations or MULTISET counts of non-string elements) run through Avro-based serialization.","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."],"exampleFix":"// before\nDataTypes.MAP(DataTypes.INT(), DataTypes.DOUBLE())\n// after\nDataTypes.MAP(DataTypes.STRING(), DataTypes.DOUBLE())","handlingStrategy":"validation","validationCode":"if (type instanceof MapType) {\n  LogicalType key = ((MapType) type).getKeyType();\n  Preconditions.checkArgument(key.is(LogicalTypeFamily.CHARACTER_STRING),\n      \"Map key must be STRING for Avro, got \" + key.asSummaryString());\n} else if (type instanceof MultisetType) {\n  LogicalType el = ((MultisetType) type).getElementType();\n  Preconditions.checkArgument(el.is(LogicalTypeFamily.CHARACTER_STRING),\n      \"Multiset element key must be STRING for Avro, got \" + el.asSummaryString());\n}","typeGuard":"boolean hasStringMapKeys(LogicalType t) {\n  if (t instanceof MapType m) return m.getKeyType().is(LogicalTypeFamily.CHARACTER_STRING);\n  if (t instanceof MultisetType ms) return ms.getElementType().is(LogicalTypeFamily.CHARACTER_STRING);\n  return true;\n}","tryCatchPattern":"try {\n  Schema s = AvroSchemaConverter.convertToSchema(rowType);\n} catch (UnsupportedOperationException e) {\n  // cast map keys to STRING or re-model as ARRAY<ROW<K,V>> and retry\n}","preventionTips":["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"],"tags":["avro","flink","map-type","schema-conversion"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}