{"record":{"id":"99cbb2c30c81f68e","repo":"apache/seatunnel","slug":"failed-to-discover-captured-tables-for-enumerator","errorCode":null,"errorMessage":"Failed to discover captured tables for enumerator","messagePattern":"Failed to discover captured tables for enumerator","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/base/source/IncrementalSource.java","lineNumber":349,"sourceCode":"                            new SnapshotOnlySplitAssigner<>(\n                                    assignerContext,\n                                    enumeratorContext.currentParallelism(),\n                                    remainingTables,\n                                    isTableIdCaseSensitive,\n                                    dataSourceDialect);\n                } else {\n                    splitAssigner =\n                            new HybridSplitAssigner<>(\n                                    assignerContext,\n                                    enumeratorContext.currentParallelism(),\n                                    incrementalParallelism,\n                                    remainingTables,\n                                    isTableIdCaseSensitive,\n                                    dataSourceDialect,\n                                    offsetFactory);\n                }\n            } catch (Exception e) {\n                throw new RuntimeException(\"Failed to discover captured tables for enumerator\", e);\n            }\n        } else {\n            splitAssigner =\n                    new IncrementalSplitAssigner<>(\n                            assignerContext, incrementalParallelism, offsetFactory);\n        }\n\n        return new IncrementalSourceEnumerator(enumeratorContext, splitAssigner);\n    }\n\n    @Override\n    public SourceSplitEnumerator<SourceSplitBase, PendingSplitsState> restoreEnumerator(\n            SourceSplitEnumerator.Context<SourceSplitBase> enumeratorContext,\n            PendingSplitsState checkpointState)\n            throws Exception {\n        // Load the JDBC driver in to DriverManager\n        if (driverName().isPresent()) {\n            try {","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/base/source/IncrementalSource.java#L331-L367","documentation":"IncrementalSource.createEnumerator builds the split assigner by first discovering the captured tables (via a dialect-specific table discovery). Any exception during discovery is wrapped in a RuntimeException with this message, preserving the cause. It signals the enumerator could not determine the set of tables to capture.","triggerScenarios":"createEnumerator is invoked at job start (non-restore path) and the underlying discovery — listing tables/schemas via JDBC metadata against the source database — throws (bad credentials, missing database, network failure, driver error).","commonSituations":"Wrong hostname/port/credentials in CDC config, source database user lacking metadata privileges, database name pattern matching zero tables, or the database being temporarily unreachable at job startup.","solutions":["Read the cause chain for the real error (SQL exception, auth failure, network timeout) and fix it","Verify hostname, port, username, password and database-name/table-name patterns in the config","Grant the CDC user SELECT and metadata access on the databases/tables being captured","Confirm the database is reachable from SeaTunnel workers, then resubmit the job"],"exampleFix":"// before\n\"database-names\" = [\"prod_db\"]\n\"username\" = \"cdc_user\"   // no privileges on prod_db -> discovery fails\n// after\nGRANT SELECT ON prod_db.* TO 'cdc_user'@'%';\n// discovery succeeds","handlingStrategy":"retry","validationCode":"// pre-flight: verify metadata access and that patterns match tables\ntry (Connection c = DriverManager.getConnection(url, user, pass);\n     ResultSet rs = c.getMetaData().getTables(db, null, \"%\", new String[]{\"TABLE\"})) {\n    if (!rs.next()) throw new IllegalStateException(\"No tables matched database-names/table-names pattern\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    enumerator = source.createEnumerator(context);\n} catch (RuntimeException e) {\n    Throwable root = e.getCause();  // real discovery failure (SQL/auth/network)\n    LOG.error(\"Table discovery failed: {}\", root == null ? e : root.getMessage());\n}","preventionTips":["Test DB credentials and metadata privileges before job submission","Ensure database/table name patterns match at least one table","Check network reachability from workers to the source database"],"tags":["cdc","enumerator","table-discovery","jdbc"],"backgroundTag":"database-query-failed","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}