apache/seatunnel · error · IllegalArgumentException
env. .mode=ROUTE requires env. .sink.plugin_name to be…
Error message
env.%s.mode=ROUTE requires env.%s.sink.plugin_name to be configured.
What it means
IllegalArgumentException from ErrorHandlerConfigUtil.buildStageConfig when a stage's error-handler mode is ROUTE but no error-sink writer is configured (sinkConfig null or not configured). ROUTE mode must know where to send bad rows, so the job is rejected at config validation.
Solutions
- Add sink { plugin_name = "..." } under the stage error-handler block (e.g. Console, JDBC, File).
- Verify the exact env key prefix matches the stage key shown in the error message.
- Switch mode to FAIL or IGNORE if you don't actually need to route bad rows.
Example fix
// before
error-handler { mode = ROUTE }
// after
error-handler { mode = ROUTE
sink { plugin_name = "Console" } } Defensive patterns
Strategy: validation
Validate before calling
if ("ROUTE".equalsIgnoreCase(mode) && !config.hasPath("sink.plugin_name")) {
throw new IllegalArgumentException("mode=ROUTE requires error-handler sink.plugin_name");
} Try / catch
try { buildStageConfig(stage, global); } catch (IllegalArgumentException e) { if (e.getMessage().contains("ROUTE requires")) { addSinkPluginName(); } } Prevention
- Always pair mode=ROUTE with a sink { plugin_name = ... } block
- Recheck stage configs after copy-pasting between stages
- Run config validation in CI for SeaTunnel job files
When it happens
Trigger: Setting env.<stage>.mode = ROUTE (or global mode=ROUTE) without env.<stage>.sink.plugin_name (or a sufficiently complete sink block).
Common situations: Copy-pasting a stage config and forgetting the sink sub-block; specifying sink options like plugin_type but omitting plugin_name; global DISABLE config edited to ROUTE without adding a sink.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- accessId and accesskey must be provided when sts_token is…
- Agent config is not a readable file
- agent.id must be non-empty after resolution.
- At least one sink plugin must be configured.
- At least one source plugin must be configured.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/2d80a6b3e793c13f.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/task/error/ErrorHandlerConfigUtil.java:107
boolean includeStacktrace = getBoolean(stage, global, "include_stacktrace", false);
boolean includeOriginalData = getBoolean(stage, global, "include_original_data", false);
String dataFormatStr = getString(stage, global, "original_data_format", "TEXT");
if (!"TEXT".equalsIgnoreCase(dataFormatStr)) {
throw new IllegalArgumentException(
"Unsupported original_data_format='"
+ dataFormatStr
+ "'. Current version only supports TEXT.");
}
OriginalDataFormat originalDataFormat = OriginalDataFormat.TEXT;
int originalDataMaxLength =
getNonNegativeInt(stage, global, "original_data_max_length", 8192);
ErrorSinkConfig sinkConfig = buildErrorSinkConfig(stage, global);
if (mode == ErrorHandlerMode.ROUTE && (sinkConfig == null || !sinkConfig.isConfigured())) {
throw new IllegalArgumentException(
String.format(
"env.%s.mode=ROUTE requires env.%s.sink.plugin_name to be configured.",
stageKey, stageKey));
}
return StageErrorConfig.builder()
.mode(mode)
.sink(sinkConfig)
.maxErrorRatio(maxErrorRatio)
.maxErrorRatioMinRecords(maxErrorRatioMinRecords)
.maxErrorRecords(maxErrorRecords)
.queueCapacity(queueCapacity)
.queueOverflowPolicy(overflowPolicy)
.includeStacktrace(includeStacktrace)
.includeOriginalData(includeOriginalData)
.originalDataFormat(originalDataFormat)
.originalDataMaxLength(originalDataMaxLength)
.build();View on GitHub (pinned to cf67b549a7)