{"record":{"id":"14365a0f4a3332b7","repo":"apache/seatunnel","slug":"common-02-14365a","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/CanalJsonSerializationSchema.java","lineNumber":99,"sourceCode":"            } else {\n                reuse.setField(0, null);\n            }\n\n            reuse.setField(1, new SeaTunnelRow[] {row});\n            reuse.setField(2, rowKind2String(row.getRowKind()));\n\n            if (!StringUtils.isEmpty(row.getTableId())) {\n                reuse.setField(3, TablePath.of(row.getTableId()).getDatabaseName());\n                reuse.setField(4, TablePath.of(row.getTableId()).getTableName());\n            }\n\n            if (row.getOptions() != null && row.getOptions().containsKey(EVENT_TIME.getName())) {\n                reuse.setField(5, row.getOptions().get(EVENT_TIME.getName()));\n            }\n\n            return jsonSerializer.serialize(reuse);\n        } catch (Throwable t) {\n            throw CommonError.jsonOperationError(FORMAT, row.toString(), t);\n        }\n    }\n\n    private String rowKind2String(RowKind rowKind) {\n        switch (rowKind) {\n            case INSERT:\n            case UPDATE_AFTER:\n                if (mergeUpdateEventFlag && rowKind.equals(RowKind.UPDATE_AFTER)) {\n                    return OP_UPDATE;\n                }\n                return OP_INSERT;\n            case UPDATE_BEFORE:\n            case DELETE:\n                return OP_DELETE;\n            default:\n                throw new SeaTunnelJsonFormatException(\n                        CommonErrorCodeDeprecated.UNSUPPORTED_OPERATION,\n                        String.format(\"Unsupported operation %s for row kind.\", rowKind));","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/canal/CanalJsonSerializationSchema.java#L81-L117","documentation":"CanalJsonSerializationSchema.serialize wraps any Throwable from building or JSON-serializing the internal reuse row into jsonOperationError. The offending SeaTunnelRow's toString is embedded. It means the row did not match the schema the Canal serializer expects (wrong arity, incompatible field types) or Jackson failed to serialize it.","triggerScenarios":"serialize(SeaTunnelRow) is called with a row whose field count/type differs from the Canal JSON row type (database schema + 'type','data','old','ts' metadata), or whose values (e.g. byte[]/BigDecimal) cannot be JSON-serialized.","commonSituations":"Upstream transform changed row arity or types before the sink; event-time option (EVENT_TIME) holds a non-serializable type; null rows or rows of the wrong RowKind passed to a Canal-format sink; schema drift between source and sink.","solutions":["Compare row.toString() from the error against the declared sink schema and fix the producing transform/source so field types match","Verify that the EVENT_TIME option value is a JSON-serializable type (e.g. timestamp string or long millis)","Regenerate/align the database schema used to build the serializer so it matches incoming rows","Catch in a test (runTest) with the exact row to reproduce, and fix the data or schema before deploying"],"exampleFix":"// before: row has 4 fields but Canal schema expects 6 (incl. 'type','ts')\nrow = new SeaTunnelRow(new Object[]{id, name});\n// after: construct row matching createJsonRowType arity\nrow = new SeaTunnelRow(new Object[]{before, after, \"UPDATE\", ts, ...});","handlingStrategy":"validation","validationCode":"// before serialize, check row conforms to canal schema\nif (row.getArity() != expectedType.getTotalFields()) {\n    throw new IllegalArgumentException(\"Row arity mismatch: \" + row);\n}","typeGuard":"boolean matchesCanalSchema(SeaTunnelRow row, SeaTunnelRowType t) {\n    return row != null && row.getArity() == t.getTotalFields();\n}","tryCatchPattern":"try {\n    byte[] out = serializer.serialize(row);\n} catch (SeaTunnelRuntimeException e) {\n    log.error(\"Cannot serialize row {} to canal JSON\", row, e);\n    throw e; // serialization failure should fail fast\n}","preventionTips":["Keep transforms between source and canal sink arity/type-stable","Store EVENT_TIME as a JSON-serializable scalar","Unit-test serialization of representative rows","Regenerate sink schema after upstream DDL changes"],"tags":["json","serialization","canal","schema"],"backgroundTag":"json-serialization-failed","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}