apache/seatunnel · error · JobDefineCheckException
The source/transform(%s) is not configured with '%s' option
Error message
The source/transform(%s) is not configured with '%s' option
What it means
checkExistTableId requires every source/transform in a complex graph to declare a plugin_output table id. If the option is absent, JobDefineCheckException wrapping an OptionValidationException for PLUGIN_OUTPUT is thrown. In multi-table DAGs, producers must be identifiable by their output table id.
Source
Thrown at seatunnel-engine/seatunnel-engine-core/src/main/java/org/apache/seatunnel/engine/core/parse/ConfigParserUtil.java:235
private static void checkLinked(Map<String, Tuple2<Config, VertexStatus>> vertexStatusMap) {
vertexStatusMap.forEach(
(id, vertex) -> {
if (vertex._2() == VertexStatus.CREATED) {
throw new JobDefineCheckException(
String.format(
"The '%s' option configured is incorrect, this table(%s) belonging to source/transform(%s) is not used.",
PLUGIN_INPUT.key(),
id,
vertex._1().getString(PLUGIN_NAME.key())));
}
});
}
private static void checkExistTableId(List<? extends Config> configs) {
for (Config config : configs) {
if (!ReadonlyConfig.fromConfig(config).getOptional(PLUGIN_OUTPUT).isPresent()) {
throw new JobDefineCheckException(
String.format(
"The source/transform(%s) is not configured with '%s' option",
config.getString(PLUGIN_NAME.key()), PLUGIN_OUTPUT.key()),
new OptionValidationException(PLUGIN_OUTPUT));
}
}
}
private static void checkExistInputTableId(List<? extends Config> configs) {
for (Config config : configs) {
if (!ReadonlyConfig.fromConfig(config).getOptional(PLUGIN_INPUT).isPresent()) {
throw new JobDefineCheckException(
String.format(
"The transform/sink(%s) is not configured with '%s' option",
config.getString(PLUGIN_NAME.key()), PLUGIN_INPUT.key()),
new OptionValidationException(PLUGIN_INPUT));
}
}View on GitHub (pinned to cf67b549a7)
Solutions
- Add plugin_output = "unique-table-id" to every source and transform block
- Alternatively use the legacy result_table_name option if supported by the plugin
- Verify which plugin is missing the option from the plugin name in the message
- Keep ids unique across all producers in the job
Example fix
// before
source {
FakeSource {}
Jdbc { plugin_output = "db" }
}
// after
source {
FakeSource { plugin_output = "fake" }
Jdbc { plugin_output = "db" }
} Defensive patterns
Strategy: validation
Validate before calling
for (Config c : sourcesAndTransforms) {
if (!c.hasPath("plugin_output") && !c.hasPath("result_table_name")) {
throw new IllegalArgumentException("Missing plugin_output for " + c.getString("plugin_name"));
}
} Try / catch
try {
ConfigParserUtil.checkExistTableId(configs);
} catch (JobDefineCheckException e) {
log.error("Missing plugin_output: {}", e.getMessage());
throw e;
} Prevention
- Add plugin_output to every source/transform in multi-table jobs
- Use a config template that includes the field
- Document the requirement for complex DAGs
- Lint configs for the option before submit
When it happens
Trigger: A source or transform block in a complex multi-table job omits plugin_output (or result_table_name); enforced by checkExistTableId inside checkComplexGraph.
Common situations: Single-table style config (no result_table_name) extended with a second source, making it a complex graph; older configs predating the option; plugin blocks copied without adding output ids.
Understand the failure class
Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.
Related errors
- The transform/sink(%s) is not configured with '%s' option
- Source And Sink can not be null
- The value of the '%s' option of the (%s and %s) plugins is b
- The '%s' option configured in [%s] is incorrect, and the sou
- The '%s' option configured is incorrect, this table(%s) belo
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/ec4558f34b8bc6d1.
Report an issue: GitHub.