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

  1. Verify the source's produced CatalogTables/TableIds match the sink's configured table list
  2. Re-run the job after fixing upstream table discovery so sink writers are created for every source table
  3. Enable continue-on-failure options only if intentionally quarantining failing tables, and check earlier ERROR logs for writer-creation failures
  4. 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

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


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/8f3a30a3ff78c726. Report an issue: GitHub.