apache/seatunnel · error · TablestoreConnectorException
WRITE_ROW_FAILED
WRITE_ROW_FAILED
Error message
Failed to send these rows of data: '%s'.
What it means
Thrown by TableStoreSinkClient.flush() when the Alibaba Tablestore BatchWriteRowResponse reports that at least one row in the batch failed to write. The message includes the failed rows returned by the server so the developer can identify which rows were rejected and why.
Solutions
- Inspect response.getFailedRows() in the message for ErrorCode/ErrorMessage per row and fix the offending row data (primary keys, column types, sizes).
- Reduce batchList batch size to stay under Tablestore BatchWriteRow limits and avoid throttling.
- Check the target table exists with the expected primary-key schema and capacity units; enable auto-scaling or raise CU quota.
- Retry failed rows with backoff if the failure is transient throttling; otherwise fail the job with corrected data.
Example fix
// before
batchList.add(changeFor(row)); // pk value may exceed limits
// after
if (pkValue == null || pkValue.getBytes(StandardCharsets.UTF_8).length > 1024) {
throw new IllegalArgumentException("Primary key too large/null: " + row);
}
batchList.add(changeFor(row)); Defensive patterns
Strategy: try-catch
Validate before calling
// Validate rows before batching
for (SeaTunnelRow row : rows) {
if (row == null || row.getField(0) == null) throw new IllegalArgumentException("Null primary key: " + row);
} Type guard
boolean isValidRow(SeaTunnelRow r) { return r != null && r.getField(0) != null && r.getArity() == expectedSchema.size(); } Try / catch
try {
sinkWriter.write(row);
} catch (TablestoreConnectorException e) {
log.error("Batch write failed; failed rows: {}", e.getMessage(), e);
// requeue or dead-letter the rows in e.getMessage()
} Prevention
- Match primary key schema and sizes to the Tablestore table definition before writing
- Keep batch sizes within Tablestore BatchWriteRow limits
- Monitor CU usage/throttling metrics on the target table
- Log response.getFailedRows() details to diagnose per-row errors
When it happens
Trigger: syncClient.batchWriteRow(batchWriteRowRequest) returns a response where isAllSucceed() is false, e.g. row changes rejected by Tablestore due to condition check failures, invalid primary key values, throttling, or oversized rows.
Common situations: Writing rows whose primary key exceeds size limits or contains nulls; batch sizes exceeding Tablestore limits; table capacity/throttling (OTSLimitExceeded); schema drift where column types no longer match the Tablestore table; attempting conditional updates that fail RowCondition checks.
Related errors
- FLUSH_DATA_FAILED
- All fields in row are null, skipping
- COMMON-17
- COMMON_FLUSH_DATA_FAILED
- COMMON_SQL_OPERATION_FAILED
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/b9fb7d9ab93a1bf8.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-tablestore/src/main/java/org/apache/seatunnel/connectors/seatunnel/tablestore/sink/TableStoreSinkClient.java:90
public void close() throws IOException {
if (syncClient != null) {
flush();
syncClient.shutdown();
}
}
synchronized void flush() {
checkFlushException();
if (batchList.isEmpty()) {
return;
}
BatchWriteRowRequest batchWriteRowRequest = new BatchWriteRowRequest();
batchList.forEach(batchWriteRowRequest::addRowChange);
BatchWriteRowResponse response = syncClient.batchWriteRow(batchWriteRowRequest);
if (!response.isAllSucceed()) {
throw new TablestoreConnectorException(
TablestoreConnectorErrorCode.WRITE_ROW_FAILED,
String.format(
"Failed to send these rows of data: '%s'.", response.getFailedRows()));
}
batchList.clear();
}
private void checkFlushException() {
if (flushException != null) {
throw new TablestoreConnectorException(
CommonErrorCodeDeprecated.FLUSH_DATA_FAILED,
"Writing items to Tablestore failed.",
flushException);
}
}
}
View on GitHub (pinned to cf67b549a7)