apache/flink · error · UnsupportedOperationException

JSON format doesn't support non-string as key type of map. T

Error message

JSON format doesn't support non-string as key type of map. The type is: %s

What it means

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.

Source

Thrown at flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/RowDataToJsonConverters.java:274

                node = (ArrayNode) reuse;
                node.removeAll();
            }

            ArrayData array = (ArrayData) value;
            int numElements = array.size();
            for (int i = 0; i < numElements; i++) {
                Object element = elementGetter.getElementOrNull(array, i);
                node.add(elementConverter.convert(mapper, null, element));
            }

            return node;
        };
    }

    private RowDataToJsonConverter createMapConverter(
            String typeSummary, LogicalType keyType, LogicalType valueType) {
        if (!keyType.is(LogicalTypeFamily.CHARACTER_STRING)) {
            throw new UnsupportedOperationException(
                    "JSON format doesn't support non-string as key type of map. "
                            + "The type is: "
                            + typeSummary);
        }
        final RowDataToJsonConverter valueConverter = createConverter(valueType);
        final ArrayData.ElementGetter valueGetter = ArrayData.createElementGetter(valueType);
        return (mapper, reuse, object) -> {
            ObjectNode node;
            // reuse could be a NullNode if last record is null.
            if (reuse == null || reuse.isNull()) {
                node = mapper.createObjectNode();
            } else {
                node = (ObjectNode) reuse;
                node.removeAll();
            }

            MapData map = (MapData) object;
            ArrayData keyArray = map.keyArray();

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Change the sink table's map key type to STRING/VARCHAR and stringify keys in the query or a UDF
  2. Restructure to ARRAY<ROW<key K, value V>> when non-string keys must be preserved
  3. Keep two schema definitions: one for the computing pipeline, one JSON-compatible for the sink

Example fix

// before
CREATE TABLE out (m MAP<BIGINT, STRING>) WITH ('connector'='kafka', 'format'='json');

// after
CREATE TABLE out (m MAP<STRING, STRING>) WITH ('connector'='kafka', 'format'='json');
-- and CAST keys to STRING in the INSERT INTO ... SELECT
Defensive patterns

Strategy: type-guard

Validate before calling

LogicalType key = mapType.getKeyType();
if (!key.is(LogicalTypeFamily.CHARACTER_STRING)) {
    throw new IllegalArgumentException("JSON sink requires string map keys: " + key);
}

Type guard

static boolean isJsonSafeMap(MapType t) {
    return t.getKeyType().is(LogicalTypeFamily.CHARACTER_STRING);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/ceddf02177bda2fa. Report an issue: GitHub.