apache/flink · error · java.lang.IllegalStateException
Illegal JSON map data...
Error message
Illegal JSON map data...
What it means
IllegalStateException from createMapConverter's lambda when the current token is not START_OBJECT while converting a MAP column — the JSON value at that position is a scalar or array where '{' ... '}' (a JSON object) is expected. Like the array variant, it is a payload-vs-schema shape mismatch.
Source
Thrown at flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/JsonParserToRowDataConverters.java:379
final Object[] array = (Object[]) Array.newInstance(elementClass, result.size());
return new GenericArrayData(result.toArray(array));
};
}
private JsonParserToRowDataConverter 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 JsonParserToRowDataConverter keyConverter = createConverter(keyType);
final JsonParserToRowDataConverter valueConverter = createConverter(valueType);
return jp -> {
if (jp.currentToken() != JsonToken.START_OBJECT) {
throw new IllegalStateException("Illegal JSON map data...");
}
Map<Object, Object> result = new HashMap<>();
while (jp.nextToken() != JsonToken.END_OBJECT) {
Object key = keyConverter.convert(jp);
jp.nextToken();
Object value = valueConverter.convert(jp);
result.put(key, value);
}
return new GenericMapData(result);
};
}
public JsonParserToRowDataConverter createRowConverter(RowType rowType) {
final JsonParserToRowDataConverter[] fieldConverters =
rowType.getFields().stream()
.map(RowType.RowField::getType)
.map(this::createConverter)
.toArray(JsonParserToRowDataConverter[]::new);View on GitHub (pinned to 2f3c205e92)
Solutions
- Match the DDL to the real payload: ARRAY<STRING> / ARRAY<ROW<k STRING,v STRING>> for pair-lists, MAP<STRING,T> only for genuine JSON objects
- Fix the producer to emit a JSON object for map fields
- Validate a sample of the real data against the schema before deploying
Example fix
-- before
attrs MAP<STRING, INT> -- data is "attrs": [{"k":"a","v":1}]
-- after
attrs ARRAY<ROW<k STRING, v INT>> Defensive patterns
Strategy: validation
Validate before calling
JsonNode n = mapper.readTree(sample).get("attrs");
if (!n.isObject()) throw new IllegalStateException("map field must be a JSON object"); Try / catch
catch (IllegalStateException e) {
if (e.getMessage().contains("Illegal JSON map data")) {
// schema says MAP but data is not an object; fix DDL or producer
}
} Prevention
- Confirm each MAP column's payload is an object on real samples
- Keep key-value pair lists as ARRAY<ROW<...>> in DDL
When it happens
Trigger: Schema declares MAP<STRING, T> but the payload has "attrs": ["a","b"] or "attrs": 42; nested map where the value converter expects an object and finds another token.
Common situations: Producers emitting arrays of key-value pairs instead of objects; schema evolution between list and object forms; DDL written from documentation rather than real samples.
Related errors
- Illegal JSON array data...
- Illegal JSON object data...
- Unsupported map null key handling mode '%s'. Validator shoul
- Unsupported value '%s' for option %s. Supported values are %
- Failed to deserialize JSON '%s'.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/b9b53d00015ca979.
Report an issue: GitHub.