apache/flink · error · IOException
Unknown "type" value "%s". The Maxwell JSON message is '%s'
Error message
Unknown "type" value "%s". The Maxwell JSON message is '%s'
What it means
While parsing a Maxwell JSON message, the 'type' field was not one of 'insert', 'update', or 'delete' (OP_INSERT/OP_UPDATE/OP_DELETE). Because Maxwell messages can also be DDL/transaction/heartbeat events that have no row image, the deserializer refuses unknown types; with 'maxwell-json.ignore-parse-errors' = false (default) it throws IOException, otherwise it logs at debug and skips.
Source
Thrown at flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/maxwell/MaxwellJsonDeserializationSchema.java:175
if (before.isNullAt(f) && oldField.findValue(fieldNames.get(f)) == null) {
// not null fields in "old" (before) means the fields are changed
// null/empty fields in "old" (before) means the fields are not changed
// so we just copy the not changed fields into before
before.setField(f, after.getField(f));
}
}
before.setRowKind(RowKind.UPDATE_BEFORE);
after.setRowKind(RowKind.UPDATE_AFTER);
genericRowDataList.add(handleRow(row, before));
genericRowDataList.add(handleRow(row, after));
} else if (OP_DELETE.equals(type)) {
// "data" field is a row, contains deleted rows
GenericRowData delete = (GenericRowData) row.getRow(0, fieldCount);
delete.setRowKind(RowKind.DELETE);
genericRowDataList.add(handleRow(row, delete));
} else {
if (!ignoreParseErrors) {
throw new IOException(
format(
"Unknown \"type\" value \"%s\". The Maxwell JSON message is '%s'",
type, new String(message)));
}
if (LOG.isDebugEnabled()) {
LOG.debug(
"Unknown \"type\" value '{}'. The Maxwell JSON message is '{}'.",
type,
new String(message));
}
}
} catch (Throwable t) {
// a big try catch to protect the processing.
if (!ignoreParseErrors) {
throw new IOException(
format("Corrupt Maxwell JSON message '%s'.", new String(message)), t);
}
if (LOG.isDebugEnabled()) {View on GitHub (pinned to 2f3c205e92)
Solutions
- Set 'maxwell-json.ignore-parse-errors' = true on the source table to skip non-row events.
- Filter the upstream topic (Maxwell binlog filter / Kafka routing) so only row-change events reach the Flink source.
- Verify the message really is Maxwell-format (check the 'type' field values present on the topic with a console consumer).
Example fix
-- before 'format' = 'maxwell-json' -- after 'format' = 'maxwell-json', 'maxwell-json.ignore-parse-errors' = 'true'
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check the type field when tolerating non-row Maxwell events
com.fasterxml.jackson.databind.JsonNode n = MAPPER.readTree(message);
String type = n.path("type").asText("");
if (!"insert".equals(type) && !"update".equals(type) && !"delete".equals(type)) {
return; // skip DDL/heartbeat/bootstrap events
} Try / catch
try { schema.deserialize(message, collector); } catch (IOException e) { if (!ignoreParseErrors) throw e; /* else record and continue */ } Prevention
- Set 'maxwell-json.ignore-parse-errors' = true when topics carry DDL/bootstrap events.
- Filter Maxwell output upstream so only row events reach the topic.
When it happens
Trigger: A Maxwell 'bootstrap-insert', DDL, or position/heartbeat message arriving on the topic consumed by a maxwell-json table source; a hand-crafted message with a missing/mistyped 'type'; Maxwell version emitting new event types.
Common situations: Consuming a Maxwell topic that also carries DDL or bootstrap events; schema evolution events after ALTER TABLE; test data with a wrong 'type' value.
Related errors
- Unknown "op_type" value "%s". The Ogg JSON message is '%s'
- Debezium JSON serialization doesn't support '%s.%s' option b
- Please invoke DeserializationSchema#deserialize(byte[], Coll
- Corrupt Maxwell JSON message '%s'.
- Unsupported operation '%s' for row kind.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/ba1617fd2725c82c.
Report an issue: GitHub.