{"record":{"id":"746358f15993205b","repo":"apache/seatunnel","slug":"at-least-one-source-plugin-must-be-configured","errorCode":null,"errorMessage":"At least one source plugin must be configured.","messagePattern":"At least one source plugin must be configured\\.","errorType":"validation","errorClass":"ConfigCheckException","httpStatus":null,"severity":"error","filePath":"seatunnel-core/seatunnel-core-starter/src/main/java/org/apache/seatunnel/core/starter/utils/ConfigValidationUtils.java","lineNumber":133,"sourceCode":"            throw new ConfigCheckException(checkResult.getMsg());\n        }\n\n        ClassLoader parentClassLoader = Thread.currentThread().getContextClassLoader();\n        ClassLoader validationClassLoader = prepareClassLoader(config, parentClassLoader);\n        Thread.currentThread().setContextClassLoader(validationClassLoader);\n        try {\n            validateEnvironmentConfig(config);\n            JobContext jobContext = new JobContext();\n            jobContext.setJobMode(RuntimeEnvironment.getJobMode(config));\n            jobContext.setEnableCheckpoint(RuntimeEnvironment.getEnableCheckpoint(config));\n\n            List<TableInfo> sourceTables =\n                    validateSources(\n                            TypesafeConfigUtils.getConfigList(\n                                    config, Constants.SOURCE, Collections.emptyList()),\n                            jobContext);\n            if (sourceTables.isEmpty()) {\n                throw new ConfigCheckException(\"At least one source plugin must be configured.\");\n            }\n\n            List<TableInfo> outputTables =\n                    validateTransforms(\n                            sourceTables,\n                            TypesafeConfigUtils.getConfigList(\n                                    config, Constants.TRANSFORM, Collections.emptyList()),\n                            jobContext);\n\n            validateSinks(\n                    outputTables,\n                    TypesafeConfigUtils.getConfigList(\n                            config, Constants.SINK, Collections.emptyList()),\n                    jobContext);\n        } catch (ConfigCheckException e) {\n            throw e;\n        } catch (Exception e) {\n            Throwable rootException = ExceptionUtils.getRootException(e);","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-core/seatunnel-core-starter/src/main/java/org/apache/seatunnel/core/starter/utils/ConfigValidationUtils.java#L115-L151","documentation":"validate requires the job config to declare at least one source plugin under the 'source' block. If the resulting source table list is empty it throws ConfigCheckException('At least one source plugin must be configured.').","triggerScenarios":"A job config with no 'source' section, an empty source list, or a source section whose entries were filtered out by TypesafeConfigUtils.getConfigList (wrong type, e.g. source as object instead of array).","commonSituations":"Copy-pasting only the sink half of an example, renaming 'source' to something else, or writing source as a single object when a list is expected.","solutions":["Add a source { ... } block with a valid plugin to the job config","Ensure 'source' is a list of plugin configs per HOCON conventions","Verify the plugin name inside source is recognized (no silent filtering)"],"exampleFix":"// before\nenv {...}\nsink { Console {} }\n// after\nenv {...}\nsource { Fake { rows = 10 } }\nsink { Console {} }","handlingStrategy":"validation","validationCode":"boolean hasSource = config.hasPath(\"source\") && !config.getConfigList(\"source\").isEmpty(); if (!hasSource) throw new IllegalArgumentException(\"config must define a source block\");","typeGuard":null,"tryCatchPattern":"try { ConfigValidationUtils.validate(config); } catch (ConfigCheckException e) { log.error(\"Job config invalid: {}\", e.getMessage()); }","preventionTips":["Template job configs with source/sink/env blocks","Lint configs before submission","Never rename the reserved 'source' key"],"tags":["config","source","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}