{"record":{"id":"f518646a1e0a729a","repo":"apache/seatunnel","slug":"no-source-tables-were-available-after-discovery-c","errorCode":null,"errorMessage":"No source tables were available after discovery. Check source-side failed-table warnings for details.","messagePattern":"No source tables were available after discovery\\. Check source-side failed-table warnings for details\\.","errorType":"validation","errorClass":"JobDefineCheckException","httpStatus":null,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-core/src/main/java/org/apache/seatunnel/engine/core/parse/MultipleTableJobConfigParser.java","lineNumber":275,"sourceCode":"            if (isStartWithSavePoint\n                    && pipelineCheckpoints != null\n                    && !pipelineCheckpoints.isEmpty()) {\n                Preconditions.checkState(\n                        sourceConfigs.size() == pipelineCheckpoints.size(),\n                        \"The number of source configurations and pipeline checkpoints must be equal.\");\n            }\n            for (int configIndex = 0; configIndex < sourceConfigs.size(); configIndex++) {\n                Config sourceConfig = sourceConfigs.get(configIndex);\n                Tuple2<String, List<Tuple2<CatalogTable, Action>>> tuple2 =\n                        parseSource(configIndex, sourceConfig, sourceAndTransformClassLoader);\n                tableWithActionMap.put(tuple2._1(), tuple2._2());\n            }\n            boolean hasSourceTables =\n                    tableWithActionMap.values().stream().anyMatch(actions -> !actions.isEmpty());\n            if (!sourceConfigs.isEmpty()\n                    && !hasSourceTables\n                    && MultiTableFailureHelper.shouldContinueOtherTables(envOptions)) {\n                throw new JobDefineCheckException(\n                        \"No source tables were available after discovery. \"\n                                + \"Check source-side failed-table warnings for details.\");\n            }\n\n            log.info(\"start generating all transforms.\");\n            parseTransforms(transformConfigs, sourceAndTransformClassLoader, tableWithActionMap);\n\n            Thread.currentThread().setContextClassLoader(sinkClassLoader);\n            log.info(\"start generating all sinks.\");\n            List<Action> sinkActions = new ArrayList<>();\n            for (int configIndex = 0; configIndex < sinkConfigs.size(); configIndex++) {\n                Config sinkConfig = sinkConfigs.get(configIndex);\n                sinkActions.addAll(\n                        parseSink(configIndex, sinkConfig, sinkClassLoader, tableWithActionMap));\n            }\n            if (sinkActions.isEmpty() && !failedTables.isEmpty()) {\n                throw new JobDefineCheckException(\n                        buildFailureSummary(","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-core/src/main/java/org/apache/seatunnel/engine/core/parse/MultipleTableJobConfigParser.java#L257-L293","documentation":"Thrown by MultipleTableJobConfigParser.parse() when the job config declares source tables but after catalog discovery no source table yielded any reader actions. SeaTunnel ran in multi-table failure tolerance mode (continue on failed tables), every source table failed discovery, so nothing remains to build the DAG from. It is a job-definition validation error raised before job execution.","triggerScenarios":"Calling job parsing (JobConfigParser.parse / immutablePair path) when: sourceConfigs is non-empty, tableWithActionMap has no non-empty action lists, and envOptions enable shouldContinueOtherTables (skip-failed-tables tolerance mode).","commonSituations":"All source tables point to nonexistent databases/tables, wrong catalog credentials for every source, network/firewall blocking the source DB, or incompatible connector plugin missing so each table fails during discovery in tolerant mode.","solutions":["Scan earlier WARN logs for per-table failed-table messages (MultiTableFailureHelper) to find the root cause per table.","Fix catalog connection settings (url, user, password, database) in each source config.","Verify referenced tables/databases exist and are accessible with the configured credentials.","Confirm the connector plugin jar is installed in connectors/; add it via install-plugin.sh if missing.","If fail-fast behavior is preferred instead of tolerating skipped tables, disable the continue-on-failed-tables option so the first real error surfaces."],"exampleFix":"// before\nsource {\n  MySQL {\n    url = \"jdbc:mysql://localhost:3306/wrong_db\"\n    table_names = [\"inventory.orders\"]\n  }\n}\n// after\nsource {\n  MySQL {\n    url = \"jdbc:mysql://localhost:3306/inventory\"\n    table_names = [\"inventory.orders\"]\n    user = \"app\"\n    password = \"******\"\n  }\n}","handlingStrategy":"validation","validationCode":"// before submitting, verify each source table is reachable\nfor (String table : sourceTables) {\n  boolean ok = catalog.tableExists(table); // also check credentials/connectivity\n  if (!ok) throw new IllegalStateException(\"Source table not discoverable: \" + table);\n}","typeGuard":null,"tryCatchPattern":"try {\n  engine.submitJob(config);\n} catch (JobDefineCheckException e) {\n  if (e.getMessage().contains(\"No source tables were available after discovery\")) {\n    // inspect failed-table warnings, fix source catalog configs, then resubmit\n  }\n}","preventionTips":["Dry-run catalog discovery per table before submitting multi-table jobs","Keep connector plugin jars installed on all nodes","Prefer fail-fast mode in CI so root-cause errors are not masked by tolerance skips"],"tags":["job-parsing","catalog-discovery","source-tables","config-validation"],"backgroundTag":"empty-result-set","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}