{"record":{"id":"69ca4784cdf162e6","repo":"apache/beam","slug":"avro-only-supports-maps-with-string-keys","errorCode":null,"errorMessage":"Avro only supports maps with string keys","messagePattern":"Avro only supports maps with string keys","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroUtils.java","lineNumber":1255,"sourceCode":"        }\n        break;\n\n      case ARRAY:\n      case ITERABLE:\n        baseType =\n            org.apache.avro.Schema.createArray(\n                getFieldSchema(\n                    checkNotNull(fieldType.getCollectionElementType()), fieldName, namespace));\n        break;\n\n      case MAP:\n        if (checkNotNull(fieldType.getMapKeyType()).getTypeName().isStringType()) {\n          // Avro only supports string keys in maps.\n          baseType =\n              org.apache.avro.Schema.createMap(\n                  getFieldSchema(checkNotNull(fieldType.getMapValueType()), fieldName, namespace));\n        } else {\n          throw new IllegalArgumentException(\"Avro only supports maps with string keys\");\n        }\n        break;\n\n      case ROW:\n        baseType = toAvroSchema(checkNotNull(fieldType.getRowSchema()), fieldName, namespace);\n        break;\n\n      default:\n        throw new IllegalArgumentException(\"Unexpected type \" + fieldType);\n    }\n    return fieldType.getNullable() ? ReflectData.makeNullable(baseType) : baseType;\n  }\n\n  private static final Map<org.apache.avro.Schema, Function<Number, ? extends Number>>\n      NUMERIC_CONVERTERS =\n          ImmutableMap.of(\n              org.apache.avro.Schema.create(org.apache.avro.Schema.Type.INT), Number::intValue,\n              org.apache.avro.Schema.create(org.apache.avro.Schema.Type.LONG), Number::longValue,","sourceCodeStart":1237,"sourceCodeEnd":1273,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroUtils.java#L1237-L1273","documentation":"Avro's MAP type only allows string keys, while Beam Schema allows maps with arbitrary key types. During FieldType -> Avro conversion, if the map's key type is not a string type, the converter throws IllegalArgumentException because no valid Avro representation exists.","triggerScenarios":"Calling AvroUtils.getFieldSchema/toAvroSchema on a FieldType of TypeName.MAP whose getMapKeyType() is not STRING (e.g. Map<Integer, X> or MAP<BYTES,...> in the Beam schema).","commonSituations":"Converting Beam rows from sources like BigQuery/Flink that allow non-string map keys into Avro for Parquet writes; portable pipeline expansion where a coder maps non-string keys to Avro.","solutions":["Change the map key type to STRING in the Beam schema before conversion (e.g. encode integer keys as strings).","Represent the map as an ARRAY of ROW<'key','value'> records instead of a MAP, which Avro supports with any key type.","Reject/normalize non-string-key maps upstream in the pipeline before writing to Avro.","Catch IllegalArgumentException and use a schema-transformation fallback (array-of-pairs) for non-string-key maps."],"exampleFix":"// before\nField.of(\"counts\", FieldType.map(FieldType.INT64, FieldType.STRING))\n// after\nField.of(\"counts\", FieldType.map(FieldType.STRING, FieldType.STRING))\n// or an array of key/value rows:\nField.of(\"counts\", FieldType.array(FieldType.row(Field.of(\"k\", FieldType.STRING), Field.of(\"v\", FieldType.STRING))))","handlingStrategy":"validation","validationCode":"static boolean isAvroCompatibleMap(FieldType ft) {\n  return ft.getTypeName() != TypeName.MAP\n      || checkNotNull(ft.getMapKeyType()).getTypeName().isStringType();\n}","typeGuard":null,"tryCatchPattern":"try {\n  org.apache.avro.Schema s = AvroUtils.toAvroSchema(beamSchema);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"maps with string keys\")) {\n    org.apache.avro.Schema s2 = AvroUtils.toAvroSchema(mapToArrayOfPairs(beamSchema));\n  } else { throw e; }\n}","preventionTips":["Constrain Beam schemas to STRING-keyed maps whenever Avro output is possible.","Prefer array-of-ROW key/value encodings for non-string keys.","Validate map key types when building schemas from external sources.","Document the Avro string-key restriction for schema authors."],"tags":["avro","beam","map","schema-conversion","string-keys"],"backgroundTag":"invalid-argument-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}