apache/seatunnel · error · DebeziumException

Unable to find table in relational model: ${tableId}

Error message

Unable to find table in relational model: ${tableId}

What it means

Identical to the ALL-columns branch: in the else path of checkDatabaseAndTableState (database-level ALL supplemental logging enabled), each captured tableId is looked up in the relational model and a null result throws 'Unable to find table in relational model: <tableId>'. The message here uses the same string concatenation; it means a configured captured table is missing from the connector's loaded schema.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-oracle/src/main/java/io/debezium/connector/oracle/logminer/LogMinerStreamingChangeEventSource.java:906

                        // at least get the table identifier thrown in the error to debug from
                        // rather
                        // than an erroneous NPE
                        throw new DebeziumException(
                                "Unable to find table in relational model: " + tableId);
                    }
                    checkTableColumnNameLengths(table);
                }
            } else {
                // ALL supplemental logging is enabled, now check table/column lengths
                for (TableId tableId : schema.tableIds()) {
                    final Table table = schema.tableFor(tableId);
                    if (table == null) {
                        // This should never happen; however in the event something would cause it
                        // we can
                        // at least get the table identifier thrown in the error to debug from
                        // rather
                        // than an erroneous NPE
                        throw new DebeziumException(
                                "Unable to find table in relational model: " + tableId);
                    }
                    checkTableColumnNameLengths(table);
                }
            }
        } finally {
            if (pdbName != null) {
                connection.resetSessionToCdb();
            }
        }
        LOGGER.trace(
                "Database and table state check finished after {} ms",
                Duration.between(start, Instant.now()).toMillis());
    }

    /**
     * Examines the table and column names and logs a warning if any name exceeds {@link
     * #MAXIMUM_NAME_LENGTH}.

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Verify the table exists and matches the connector's include/exclude filters with exact casing.
  2. Check and repair the schema history topic (ensure the worker can read it and history recovery completes).
  3. Re-snapshot the missing table or drop it from the capture configuration.
  4. If new tables were added to the include filter, restart with a snapshot refresh (snapshot.mode=schema_only_recovery or re-snapshot) so the model contains them.

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

SELECT owner, table_name FROM all_tables
 WHERE owner || '.' || table_name IN (:configuredTableIds);

Prevention

When it happens

Trigger: execute -> checkDatabaseAndTableState, ALL supplemental logging branch: schema.tableFor(tableId) returns null for one of the captured tables while validating table/column name lengths.

Common situations: Table dropped/renamed after snapshot but still matched by include filters; stale or desynchronized schema history topic; incremental snapshot of a table absent from the relational model; identifier casing mismatch.

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/29dbfa6ea18ac5a8. Report an issue: GitHub.