apache/seatunnel · error · org.apache.seatunnel.common.exception.SeaTunnelRuntimeException
COMMON-02
COMMON-02
Error message
<identifier> JSON convert/parse '<payload>' operation failed.
What it means
The Fake source connector wraps any failure while deserializing a user-provided 'fake.rows' JSON payload into a SeaTunnelRow with this generic JSON convert/parse error (code COMMON-02), built by CommonError.jsonOperationError. It is thrown from FakeDataGenerator.convertRow when JsonDeserializationSchema.deserialize throws an IOException. This typically means the JSON in fake.rows does not match the table schema declared in the catalog table, or the JSON itself is malformed.
Source
Thrown at seatunnel-connectors-v2/connector-fake/src/main/java/org/apache/seatunnel/connectors/seatunnel/fake/source/FakeDataGenerator.java:94
this.fakeConfig = fakeConfig;
this.jsonDeserializationSchema =
fakeConfig.getFakeRows() == null
? null
: new JsonDeserializationSchema(catalogTable, false, false);
this.fakeDataRandomUtils = new FakeDataRandomUtils(fakeConfig, jobId);
}
private SeaTunnelRow convertRow(FakeConfig.RowData rowData) {
try {
SeaTunnelRow seaTunnelRow =
jsonDeserializationSchema.deserialize(rowData.getFieldsJson());
if (rowData.getKind() != null) {
seaTunnelRow.setRowKind(RowKind.valueOf(rowData.getKind()));
}
seaTunnelRow.setTableId(tableId);
return seaTunnelRow;
} catch (IOException e) {
throw CommonError.jsonOperationError("Fake", rowData.getFieldsJson(), e);
}
}
private SeaTunnelRow randomRow() {
// Generate random data according to the data type and data colum of the table
List<Column> physicalColumns = catalogTable.getTableSchema().getColumns();
List<Object> randomRow = new ArrayList<>(physicalColumns.size());
for (Column column : physicalColumns) {
randomRow.add(randomColumnValue(column));
}
SeaTunnelRow seaTunnelRow = new SeaTunnelRow(randomRow.toArray());
seaTunnelRow.setTableId(tableId);
return seaTunnelRow;
}
@VisibleForTesting
public List<SeaTunnelRow> generateFakedRows(int rowNum) {
List<SeaTunnelRow> rows = new ArrayList<>();View on GitHub (pinned to cf67b549a7)
Solutions
- Print and validate the failing payload shown in the message ('<payload>') with a JSON linter to fix syntax errors.
- Compare the JSON keys and value types in fake.rows against the columns declared in the table schema; rename keys and coerce types so they match exactly.
- If the payload is generated programmatically, ensure fieldsJson is serialized with a proper JSON serializer and is non-null/non-empty.
- For complex column types, make sure nested JSON structure (array/map/row) matches the SeaTunnel data type definition.
Example fix
// before (HOCON fake source config)
Fake {
rows = [
{ kind = INSERT, fields = {name = "a", age = "x"} } // age declared INTEGER
]
}
// after
Fake {
rows = [
{ kind = INSERT, fields = {name = "a", age = 30} }
]
} Defensive patterns
Strategy: validation
Validate before calling
// Validate the fake.rows JSON before starting the job
for (FakeConfig.RowData row : fakeConfig.getFakeRows()) {
String json = row.getFieldsJson();
if (json == null || json.trim().isEmpty()) {
throw new IllegalArgumentException("fake.rows entry has empty fieldsJson");
}
try (java.io.Reader r = new java.io.StringReader(json)) {
new com.fasterxml.jackson.databind.ObjectMapper().readTree(r); // throws on malformed JSON
}
} Try / catch
try {
SeaTunnelRow row = generator.convertRow(rowData);
} catch (org.apache.seatunnel.api.table.type.CommonErrorCode | RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("JSON convert/parse")) {
LOGGER.error("Invalid fake.rows payload: {}", rowData.getFieldsJson(), e);
return; // skip or fail fast with a clear message
}
throw e;
} Prevention
- Validate every fake.rows entry with a JSON parser and against the table schema before deploying the job.
- Keep fake.rows field names and types exactly aligned with the declared catalog table columns.
- Generate fieldsJson with a serializer rather than hand-writing JSON strings in config files.
- Test the Fake source locally with -e local before running in a cluster.
When it happens
Trigger: Thrown in FakeDataGenerator.convertRow (FakeDataGenerator.java:94) when jsonDeserializationSchema.deserialize(rowData.getFieldsJson()) raises IOException, i.e. the fieldsJson string cannot be parsed as JSON or does not conform to the CatalogTable's row type. Called via generateCustomRows whenever the Fake source config contains custom 'fake.rows'.
Common situations: 1) A malformed JSON literal in fake.rows (missing quotes, trailing comma, unescaped characters). 2) fake.rows fields not matching the declared schema (wrong column names, wrong types such as a string where an int is expected). 3) fieldsJson being null or empty because the config assembled RowData incorrectly. 4) Nested/complex types (arrays, maps, rows) whose JSON shape doesn't match the catalog table definition.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Fail to deserialize row: ${row}, table: ${tableInfo.getId()}
- COMMON_UNSUPPORTED_OPERATION
- FileConnectorErrorCode.DATA_DESERIALIZE_FAILED
- CommonErrorCodeDeprecated.ILLEGAL_ARGUMENT
- Failed to deserialize python source stdout line [{}]
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/5a313ec44a105148.
Report an issue: GitHub.