{"record":{"id":"791e10853e6c3931","repo":"apache/seatunnel","slug":"common-02-791e10","errorCode":"COMMON-02","errorMessage":"Json JSON convert/parse '<payload>' operation failed.","messagePattern":"Json JSON convert/parse '<payload>' operation failed\\.","errorType":"error_code","errorClass":"SeaTunnelRuntimeException","httpStatus":null,"severity":"error","filePath":"seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/canal/CanalJsonDeserializationSchema.java","lineNumber":215,"sourceCode":"                    for (int i = 0; i < dataNode.size(); i++) {\n                        SeaTunnelRow row = convertJsonNode(dataNode.get(i));\n                        row.setRowKind(RowKind.DELETE);\n                        if (tablePath != null && !tablePath.toString().isEmpty()) {\n                            row.setTableId(tablePath.toString());\n                        }\n                        if (tsNode != null) {\n                            MetadataUtil.setEventTime(row, tsNode.asLong());\n                        }\n                        out.collect(row);\n                    }\n                    break;\n                default:\n                    throw new IllegalStateException(\n                            String.format(\"Unknown operation type '%s'.\", op));\n            }\n        } catch (RuntimeException e) {\n            if (!ignoreParseErrors) {\n                throw CommonError.jsonOperationError(FORMAT, jsonNode.toString(), e);\n            }\n        }\n    }\n\n    private ObjectNode convertBytes(byte[] message) throws SeaTunnelRuntimeException {\n        if (message == null || message.length == 0) {\n            return null;\n        }\n\n        try {\n            return (ObjectNode) jsonDeserializer.deserializeToJsonNode(message);\n        } catch (Throwable t) {\n            if (!ignoreParseErrors) {\n                throw CommonError.jsonOperationError(FORMAT, new String(message), t);\n            }\n            return null;\n        }\n    }","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/canal/CanalJsonDeserializationSchema.java#L197-L233","documentation":"CanalJsonDeserializationSchema.deserialize wraps any RuntimeException thrown while parsing a Canal JSON message or mapping it to a SeaTunnelRow into jsonOperationError, unless ignoreParseErrors is enabled. The raw JSON payload is embedded in the message. It means the message did not conform to the expected Canal CDC envelope (op/data/old fields) or the row converters rejected the values.","triggerScenarios":"deserialize(byte[] message, Collector<SeaTunnelRow>) receives a Canal message whose JSON structure, 'op' value, or 'data' fields do not match the expected schema; converters throw RuntimeException during row conversion.","commonSituations":"Canal server emitting messages with format version mismatches or non-standard fields; topic polluted with non-CDC messages (DDL events, heartbeats); table schema changed upstream so row conversion fails; 'op' values outside the supported set hitting the IllegalStateException branch.","solutions":["Log and inspect the payload in the error message and compare it against the expected Canal JSON envelope (data, old, type, ts)","Validate the canal instance configuration so only DML events reach the connector (filter DDL/heartbeat events)","Set ignore-parse-errors=true if dirty/skippable messages should not fail the job","Refresh the connector's table schema (or restart with updated schema) if upstream DDL changed column types"],"exampleFix":"// before: job fails on any dirty message\nCanalJsonDeserializationSchema.builder(...).build();\n// after: tolerate malformed messages\nCanalJsonDeserializationSchema.builder(...).setIgnoreParseErrors(true).build();","handlingStrategy":"try-catch","validationCode":"// validate Canal envelope before deserialize\nJsonNode n = JsonUtils.stringToJsonNode(new String(message));\nif (!n.has(\"type\") || !n.has(\"data\")) throw new SkipRecordException();","typeGuard":"boolean isCanalEnvelope(JsonNode n) {\n    return n != null && n.isObject() && n.has(\"type\") && n.has(\"data\");\n}","tryCatchPattern":"try {\n    schema.deserialize(message, out);\n} catch (SeaTunnelRuntimeException e) {\n    log.warn(\"Skipping malformed canal message: {}\", new String(message), e);\n}","preventionTips":["Set ignore-parse-errors=true for dirty CDC streams","Filter DDL/heartbeat events before the connector","Keep the canal instance and connector versions aligned","Alert on message-shape changes rather than failing the job"],"tags":["json","cdc","canal","deserialization"],"backgroundTag":"json-parse-error","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}