apache/seatunnel · error · JobDefineCheckException
The transform/sink(%s) is not configured with '%s' option
Error message
The transform/sink(%s) is not configured with '%s' option
What it means
checkExistInputTableId requires every transform/sink in a complex graph to declare a plugin_input id. If absent, JobDefineCheckException wrapping an OptionValidationException for PLUGIN_INPUT is thrown. Consumers in a multi-table DAG must state which upstream table they read.
Source
Thrown at seatunnel-engine/seatunnel-engine-core/src/main/java/org/apache/seatunnel/engine/core/parse/ConfigParserUtil.java:247
});
}
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));
}
}
}
private static String getTableId(ReadonlyConfig config) {
return config.getOptional(PLUGIN_OUTPUT).orElse(DEFAULT_ID);
}
static List<String> getInputIds(ReadonlyConfig config) {
return config.getOptional(PLUGIN_INPUT).orElse(Collections.singletonList(DEFAULT_ID));
}
public static String getFactoryId(ReadonlyConfig readonlyConfig) {
String pluginName = readonlyConfig.get(PLUGIN_NAME);View on GitHub (pinned to cf67b549a7)
Solutions
- Add plugin_input = "existing-table-id" to every transform and sink block
- Alternatively use the legacy source_table_name option if supported
- Ensure the referenced id matches a plugin_output of an upstream plugin
- Check the plugin name in the message to locate the offending block
Example fix
// before
sink {
Console {}
}
// after
sink {
Console { plugin_input = "fake" }
} Defensive patterns
Strategy: validation
Validate before calling
for (Config c : transformsAndSinks) {
if (!c.hasPath("plugin_input") && !c.hasPath("source_table_name")) {
throw new IllegalArgumentException("Missing plugin_input for " + c.getString("plugin_name"));
}
} Try / catch
try {
ConfigParserUtil.checkExistInputTableId(configs);
} catch (JobDefineCheckException e) {
log.error("Missing plugin_input: {}", e.getMessage());
throw e;
} Prevention
- Add plugin_input to every transform/sink in multi-table jobs
- Use a config template that includes the field
- Verify ids match an upstream plugin_output
- Lint configs before submission
When it happens
Trigger: A transform or sink block in a complex multi-table job omits plugin_input (or source_table_name); enforced by checkExistInputTableId inside checkComplexGraph.
Common situations: Simple single-table config (where plugin_input is optional) grew into a multi-table graph by adding a second source; plugin blocks copied without adding input ids; ambiguous consumer after renaming tables.
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 source/transform(%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/bcf2436facd3353e.
Report an issue: GitHub.