{"record":{"id":"ceddf02177bda2fa","repo":"apache/flink","slug":"json-format-doesn-t-support-non-string-as-key-type-ceddf0","errorCode":null,"errorMessage":"JSON format doesn't support non-string as key type of map. The type is: %s","messagePattern":"JSON format doesn't support non-string as key type of map\\. The type is: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/RowDataToJsonConverters.java","lineNumber":274,"sourceCode":"                node = (ArrayNode) reuse;\n                node.removeAll();\n            }\n\n            ArrayData array = (ArrayData) value;\n            int numElements = array.size();\n            for (int i = 0; i < numElements; i++) {\n                Object element = elementGetter.getElementOrNull(array, i);\n                node.add(elementConverter.convert(mapper, null, element));\n            }\n\n            return node;\n        };\n    }\n\n    private RowDataToJsonConverter createMapConverter(\n            String typeSummary, LogicalType keyType, LogicalType valueType) {\n        if (!keyType.is(LogicalTypeFamily.CHARACTER_STRING)) {\n            throw new UnsupportedOperationException(\n                    \"JSON format doesn't support non-string as key type of map. \"\n                            + \"The type is: \"\n                            + typeSummary);\n        }\n        final RowDataToJsonConverter valueConverter = createConverter(valueType);\n        final ArrayData.ElementGetter valueGetter = ArrayData.createElementGetter(valueType);\n        return (mapper, reuse, object) -> {\n            ObjectNode node;\n            // reuse could be a NullNode if last record is null.\n            if (reuse == null || reuse.isNull()) {\n                node = mapper.createObjectNode();\n            } else {\n                node = (ObjectNode) reuse;\n                node.removeAll();\n            }\n\n            MapData map = (MapData) object;\n            ArrayData keyArray = map.keyArray();","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/RowDataToJsonConverters.java#L256-L292","documentation":"Thrown by RowDataToJsonConverters.createMapConverter when the schema for a JSON sink contains a MAP type whose key type is not in the CHARACTER_STRING family. JSON object keys must be strings, so the serializer cannot emit maps like MAP<INT, STRING>. Fails at converter-construction time before any record is written.","triggerScenarios":"A table using format 'json' for output (e.g. Kafka sink with 'format'='json', or the JSON filesystem sink) whose DDL declares MAP with a non-string key. Throws when JsonRowDataSerializationSchema is created, at job startup.","commonSituations":"Reusing an input DDL with numeric map keys for the sink side; porting schemas from formats that allow arbitrary map keys (Parquet/Avro-ish maps, internal maps); map<timestamp,...> window-result tables written to JSON.","solutions":["Change the sink table's map key type to STRING/VARCHAR and stringify keys in the query or a UDF","Restructure to ARRAY<ROW<key K, value V>> when non-string keys must be preserved","Keep two schema definitions: one for the computing pipeline, one JSON-compatible for the sink"],"exampleFix":"// before\nCREATE TABLE out (m MAP<BIGINT, STRING>) WITH ('connector'='kafka', 'format'='json');\n\n// after\nCREATE TABLE out (m MAP<STRING, STRING>) WITH ('connector'='kafka', 'format'='json');\n-- and CAST keys to STRING in the INSERT INTO ... SELECT","handlingStrategy":"type-guard","validationCode":"LogicalType key = mapType.getKeyType();\nif (!key.is(LogicalTypeFamily.CHARACTER_STRING)) {\n    throw new IllegalArgumentException(\"JSON sink requires string map keys: \" + key);\n}","typeGuard":"static boolean isJsonSafeMap(MapType t) {\n    return t.getKeyType().is(LogicalTypeFamily.CHARACTER_STRING);\n}","tryCatchPattern":null,"preventionTips":["Keep a separate JSON-compatible sink DDL","Cast numeric keys to STRING in the INSERT SELECT","Add a CI schema lint step for sink tables"],"tags":["json","map","schema","serialization","startup"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}