{"record":{"id":"e099d49d0619c9ff","repo":"apache/beam","slug":"only-strings-allowd-as-map-keys-when-converting-to-json","errorCode":null,"errorMessage":"Only strings allowd as map keys when converting to JSON, found {beam_type}","messagePattern":"Only strings allowd as map keys when converting to JSON, found (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/yaml/json_utils.py","lineNumber":282,"sourceCode":"\n  def __getstate__(self):\n    return {'_constructor': self._constructor, '_value': None}\n\n\ndef row_to_json(beam_type: schema_pb2.FieldType) -> Callable[[Any], Any]:\n  \"\"\"Returns a callable converting rows of the given type to Json objects.\"\"\"\n  type_info = beam_type.WhichOneof(\"type_info\")\n  if type_info == \"atomic_type\":\n    return lambda value: value\n  elif type_info == \"array_type\":\n    element_converter = row_to_json(beam_type.array_type.element_type)\n    return lambda value: [element_converter(e) for e in value]\n  elif type_info == \"iterable_type\":\n    element_converter = row_to_json(beam_type.iterable_type.element_type)\n    return lambda value: [element_converter(e) for e in value]\n  elif type_info == \"map_type\":\n    if beam_type.map_type.key_type.atomic_type != schema_pb2.STRING:\n      raise TypeError(\n          f'Only strings allowd as map keys when converting to JSON, '\n          f'found {beam_type}')\n    value_converter = row_to_json(beam_type.map_type.value_type)\n    return lambda value: {k: value_converter(v) for (k, v) in value.items()}\n  elif type_info == \"row_type\":\n    converters = {\n        field.name: row_to_json(field.type)\n        for field in beam_type.row_type.schema.fields\n    }\n    return lambda row: {\n        name: converted\n        for (name, convert) in converters.items()\n        # To filter out nullable fields in rows\n        if (converted := convert(getattr(row, name, None))) is not None\n    }\n  elif type_info == \"logical_type\":\n    return lambda value: value\n  else:","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/yaml/json_utils.py#L264-L300","documentation":"row_to_json converts Beam Rows to JSON-shaped values following a Beam schema. JSON objects only support string keys, so when a map-typed field's key type is not STRING, a TypeError is raised (message contains the typo 'allowd'). Non-string-keyed maps cannot be serialized to JSON.","triggerScenarios":"Writing Beam Rows whose schema has map<int, X> (or bytes/other key types) through row_to_json, json_formater, or row_validator, e.g. a yaml WriteToJson transform with a declared int-keyed map field.","commonSituations":"Source data (Avro/Parquet/Protobuf maps) with non-string keys being exported to JSON; schema inferred from such a source then used with a JSON sink in a yaml pipeline.","solutions":["Convert map keys to strings before serialization (transform the row to use string keys)","Change the schema so the map key_type is string","Model the data as a repeated row of {key, value} fields instead of a map","Emit to a format that supports non-string keys (Parquet/Avro) instead of JSON"],"exampleFix":"# before\nschema: \"map<integer, string> counts\"\n# after\nschema: \"array<row<key: string, value: string>> counts\"","handlingStrategy":"validation","validationCode":"from apache_beam.typehelp import schema_pb2\ndef assert_json_safe_rows(rows, beam_schema):\n    for f in beam_schema.fields:\n        t = f.type\n        if t.WhichOneof('type_info') == 'map_type' and t.map_type.key_type.atomic_type != schema_pb2.STRING:\n            raise TypeError(f'Field {f.name}: non-string map keys cannot be written as JSON')","typeGuard":"def is_json_safe_map(beam_type) -> bool:\n    if beam_type.WhichOneof('type_info') != 'map_type':\n        return True\n    return beam_type.map_type.key_type.atomic_type == schema_pb2.STRING","tryCatchPattern":"try:\n    out = json_formater(beam_schema, json_schema)(row)\nexcept TypeError as e:\n    raise TypeError(f'Stringify map keys or use a key/value row list: {e}') from e","preventionTips":["Stringify map keys in a prior transform before JSON sinks","Prefer array<row<key, value>> modeling when keys must be non-strings","Match sink format capabilities: use Parquet/Avro for non-string-keyed maps"],"tags":["python","apache-beam","json","type-mismatch"],"backgroundTag":"type-mismatch","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"}