apache/seatunnel · error · RuntimeException
MultiTableWriterRunnable can't find writer for tableId:
Error message
MultiTableWriterRunnable can't find writer for tableId:
What it means
Thrown by MultiTableWriterRunnable.writeRow when an incoming SeaTunnelRow's tableId has no matching writer in the tableIdWriterMap. The multi-table sink dispatches rows to per-table writers; a row whose table id was never registered (or whose writer was quarantined/failed) cannot be routed, so the runnable fails the record deliberately.
Source
Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/sink/multitablesink/MultiTableWriterRunnable.java:199
*/
void writeRow(SeaTunnelRow row) throws Throwable {
if (row.getArity() == 0) {
log.debug(
"Skip control SeaTunnelRow with zero arity in MultiTableWriterRunnable: {}",
row);
return;
}
SinkWriter<SeaTunnelRow, ?, ?> writer = tableIdWriterMap.get(row.getTableId());
if (writer == null) {
if (allowSingleWriterFallback && tableIdWriterMap.size() == 1) {
writer = tableIdWriterMap.values().stream().findFirst().get();
currentTableId = tableIdWriterMap.keySet().stream().findFirst().get();
} else if (continueOnTableFailure) {
log.debug("Skip row for quarantined table {}", row.getTableId());
return;
} else {
currentTableId = row.getTableId();
throw new RuntimeException(
"MultiTableWriterRunnable can't find writer for tableId: "
+ row.getTableId());
}
} else {
currentTableId = row.getTableId();
}
try {
beginCollectedRowErrorOutcomeProbe(row);
writeWithRetry(writer, row, currentTableId);
if (!consumeCollectedRowErrorOutcome(row)) {
writeSuccessHandler.accept(row);
}
} catch (InterruptedException interruptedException) {
clearCollectedRowErrorOutcomeProbe(row);
throw interruptedException;
} catch (Throwable error) {
clearCollectedRowErrorOutcomeProbe(row);
try {View on GitHub (pinned to cf67b549a7)
Solutions
- Verify the source's produced CatalogTables/TableIds match the sink's configured table list
- Re-run the job after fixing upstream table discovery so sink writers are created for every source table
- Enable continue-on-failure options only if intentionally quarantining failing tables, and check earlier ERROR logs for writer-creation failures
- Upgrade/patch connectors if a connector emits table ids inconsistent with its catalog tables
Example fix
// before row with tableId "db.new_table" arrives; sink has writers only for db.table1, db.table2 -> RuntimeException // after ensure source table list and sink table config both include db.new_table before submitting the job
Defensive patterns
Strategy: validation
Validate before calling
if (!tableIdWriterMap.containsKey(row.getTableId())) { log.warn("No writer for tableId {}", row.getTableId()); return; } Type guard
boolean hasWriter = tableIdWriterMap.containsKey(row.getTableId());
Try / catch
try { runnable.writeRow(row); } catch (RuntimeException e) { /* inspect tableId vs writer map */ } Prevention
- Keep sink table config and source table list in sync
- Log and reconcile writer map contents at job start
- Enable continue-on-failure only deliberately
When it happens
Trigger: A row arrives whose TableId is not a key of tableIdWriterMap: the upstream source emitted a tableId the sink never created a writer for, writer creation for that table failed earlier, or writers were removed after a table error without continueOnTableFailure enabled.
Common situations: Multi-table (whole-database) synchronization where the source discovers a new table at runtime that the sink's writer map does not cover; schema/table list changed between split enumeration and writing; upstream connector bug emitting mismatched table ids.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Elasticsearch multi-table writer requires ElasticsearchMulti
- All candidate sink tables were skipped in Flink starter.
- All candidate sink tables were skipped in Flink starter.
- All candidate sink tables were skipped in Spark starter.
- All candidate sink tables were skipped in Spark starter.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/8f3a30a3ff78c726.
Report an issue: GitHub.