{"record":{"id":"b20151a0e6241ed4","repo":"apache/seatunnel","slug":"all-candidate-sink-tables-were-skipped-during-job","errorCode":null,"errorMessage":"All candidate sink tables were skipped during job parsing.","messagePattern":"All candidate sink tables were skipped during job parsing\\.","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":292,"sourceCode":"                    && 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(\n                                \"All candidate sink tables were skipped during job parsing.\"));\n            }\n            if (!failedTables.isEmpty()) {\n                log.warn(\n                        buildFailureSummary(\n                                \"Some tables were skipped during multi-table job parsing.\"));\n            }\n            Set<URL> factoryUrls = getUsedFactoryUrls(sinkActions);\n            return new ImmutablePair<>(sinkActions, factoryUrls);\n        } finally {\n            Thread.currentThread().setContextClassLoader(parentClassLoader);\n            if (classLoaderService != null) {\n                classLoaderService.releaseClassLoader(\n                        Long.parseLong(jobConfig.getJobContext().getJobId()), sourceJars);\n                classLoaderService.releaseClassLoader(\n                        Long.parseLong(jobConfig.getJobContext().getJobId()), sinkConnectorJars);\n            }","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-core/src/main/java/org/apache/seatunnel/engine/core/parse/MultipleTableJobConfigParser.java#L274-L310","documentation":"Thrown by MultipleTableJobConfigParser.parse() when every sink table config was skipped during parsing (no sink actions were produced) and at least one table previously failed. Because the multi-table tolerance mode silently skips broken sinks, this final check guarantees a job is never submitted with zero sinks; it aggregates the per-table failures into a summary message.","triggerScenarios":"parseSink returned no actions for any sink config (all skipped due to failed upstream tables or sink-side discovery errors) while failedTables is non-empty.","commonSituations":"Sink table_names reference missing tables, sink catalog credentials wrong for all tables, schema mismatch caused auto create mode failures, or upstream source failures propagated so all sink branches were dropped.","solutions":["Read the aggregated failure summary in the exception and the WARN lines listing each skipped table's cause.","Fix each sink table's catalog config (connection, credentials, table existence).","Enable auto-create-table / CREATE_SCHEMA_SAVE_MODE appropriately if sink tables should be created.","Verify the sink connector plugin jar is present on the cluster.","If failures are intentional, remove those tables from the config rather than relying on silent skips."],"exampleFix":"// before\nsink {\n  Jdbc {\n    url = \"jdbc:mysql://localhost:3306/missing_schema\"\n    table = \"results.summary\"\n  }\n}\n// after\nsink {\n  Jdbc {\n    url = \"jdbc:mysql://localhost:3306/results\"\n    table = \"results.summary\"\n    generate_sink_sql = true\n    schema_save_mode = \"CREATE_SCHEMA_WHEN_NOT_EXIST\"\n  }\n}","handlingStrategy":"validation","validationCode":"// pre-check sink tables exist (or will be auto-created)\nfor (String table : sinkTables) {\n  if (!autoCreate && !catalog.tableExists(table)) {\n    throw new IllegalStateException(\"Sink table missing: \" + table);\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  engine.submitJob(config);\n} catch (JobDefineCheckException e) {\n  if (e.getMessage().startsWith(\"All candidate sink tables were skipped\")) {\n    // read the aggregated summary for per-table causes\n  }\n}","preventionTips":["Validate sink table names and permissions before submission","Set schema_save_mode explicitly when tables may not exist","Review WARN-level failed-table logs after every parse failure"],"tags":["job-parsing","sink-tables","catalog-discovery","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"}