apache/seatunnel · error · org.apache.seatunnel.api.configuration.util.OptionValidationException
' ' duplicate in ' '.
Error message
%s '%s' duplicate in '%s'.
What it means
Validation guard inside OptionRule's builder fired while processing an optional()/required() entry: the option key being added already appears in the rule's option list (or collides with an entry under an OPTIONS_OPTION_WITH_CONSTRAINT block). The message names the option type ('required', 'optional', etc.) and the offending key, so the duplicate declaration in the factory's OptionRule is the input at fault.
Solutions
- Search the factory's OptionRule for the duplicated key reported in the message and delete one of the declarations
- Share a single static Option constant across rules instead of re-declaring OptionTypes with the same key
- Add a unit test asserting the rule builds without throwing to catch regressions
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/OptionRule.java:564 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/bf8ae88545c0f677.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-api/src/main/java/org/apache/seatunnel/api/configuration/util/OptionRule.java:564
}
private void verifyOptionOptionsDuplicate(
@NonNull Option<?> option, @NonNull String currentOptionType) {
verifyDuplicateWithOptionOptions(option, currentOptionType);
boolean hasOptionsOptionWithConstraint =
CurrentOptionType.OPTIONS_OPTION_WITH_CONSTRAINT.type.equals(currentOptionType);
requiredOptions.forEach(
requiredOption -> {
if (hasOptionsOptionWithConstraint
&& (requiredOption
instanceof RequiredOption.ExclusiveRequiredOptions
|| requiredOption
instanceof RequiredOption.BundledRequiredOptions)) {
return;
}
if (requiredOption.getOptions().contains(option)) {
throw new OptionValidationException(
String.format(
"%s '%s' duplicate in '%s'.",
currentOptionType,
option.key(),
requiredOption.getClass().getSimpleName()));
}
});
}
private void verifyConditionalExists(@NonNull Option<?> option) {
boolean inOptions = optionalOptions.contains(option);
AtomicBoolean inRequired = new AtomicBoolean(false);
requiredOptions.forEach(
requiredOption -> {
if (requiredOption.getOptions().contains(option)) {
inRequired.set(true);
}
});View on GitHub (pinned to cf67b549a7)