junit-team/junit5 · error · CommandLine.ParameterException
Duplicate key ' ' for values ' ' and ' '.
Error message
Duplicate key '%s' for values '%s' and '%s'.
What it means
TestDiscoveryOptionsMixin.validateUnique() enforces that a --config KEY=VALUE pair, when repeated with the same key, must supply the same value. If the same key is given with a conflicting value, picocli.ParameterException is thrown, so the CLI prints usage and exits with an error code. Same-key/same-value is allowed (idempotent).
Solutions
- Search the full command line for repeated --config entries with the same KEY and reconcile to a single VALUE.
- Centralize configuration parameter values in one place (a script variable) so they cannot diverge.
- If both values are legitimately needed, use two different keys or pick one as authoritative.
- Re-run after removing the conflicting duplicate.
Example fix
# before java -jar junit-platform-console-standalone.jar execute --config junit.jupiter.testinstance.lifecycle.default=per_class --config junit.jupiter.testinstance.lifecycle.default=per_method # after: pick one value java -jar junit-platform-console-standalone.jar execute --config junit.jupiter.testinstance.lifecycle.default=per_method
Defensive patterns
Strategy: validation
Validate before calling
// In a wrapper, dedupe --config KEY=VALUE pairs and detect conflicts before invoking the launcher.
import java.util.*;
Map<String,String> seen = new HashMap<>();
List<String> configArgs = collectConfigArgs(args); // e.g. each "--config KEY=VALUE"
for (String a : configArgs) {
String[] kv = a.replaceFirst("^--config\\s+=?", "").split("=", 2);
String key = kv[0].trim(), val = kv.length > 1 ? kv[1] : "";
if (seen.containsKey(key) && !seen.get(key).equals(val))
throw new IllegalArgumentException("Conflicting --config for key '" + key + "': '" + seen.get(key) + "' vs '" + val + "'");
seen.put(key, val);
}
Prevention
- Source all --config values from a single map in your build script so they cannot diverge.
- Treat any repeated --config key as a red flag during code/script review.
- Document the canonical config values once and reuse them everywhere.
When it happens
Trigger: Using --config multiple times with the same KEY but different VALUE in one invocation: e.g. '--config junit.jupiter.displayname.generator.default=A --config junit.jupiter.displayname.generator.default=B'. picocli accumulates them into the map; the setter detects the conflict.
Common situations: Build scripts or Gradle/Maven plugins that concatenate --config from multiple sources and accidentally disagree on a value; copy-pasted CLI args where one value is stale; CI templates overriding a config that was set earlier in the same command line.
Related errors
- ${e.getMessage()}
- Missing required subcommand
- Cannot override the standard style 'NONE'
- Could not open color palette properties file
- Could not read color palette properties
AI-assisted analysis of junit-team/junit5@f070c699a0 (2026-08-11).
Data as JSON: /api/errors/1b90f3e909eecc28.
Report an issue: GitHub.
Appendix: source
Thrown at junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java:242
* on the command line.
*
* @param map the key-value pairs to add
* @throws CommandLine.ParameterException if the map already contains this key
* @see <a href="https://github.com/junit-team/junit-framework/issues/1308">#1308</a>
*/
@Option(names = "--config", paramLabel = "KEY=VALUE", arity = "1", description = "Set a configuration parameter for test discovery and execution. This option can be repeated.")
public void setConfigurationParameters(Map<String, String> map) {
for (String key : map.keySet()) {
String newValue = map.get(key);
validateUnique(key, newValue);
configurationParameters.put(key, newValue);
}
}
private void validateUnique(String key, String newValue) {
String existing = configurationParameters.get(key);
if (existing != null && !existing.equals(newValue)) {
throw new CommandLine.ParameterException(spec.commandLine(),
"Duplicate key '%s' for values '%s' and '%s'.".formatted(key, existing, newValue));
}
}
private void applyTo(TestDiscoveryOptions result) {
result.setAdditionalClasspathEntries(additionalClasspathEntries);
result.setConfigurationParametersResources(configurationParametersResources);
result.setConfigurationParameters(configurationParameters);
}
}
public TestDiscoveryOptions toTestDiscoveryOptions() {
TestDiscoveryOptions result = new TestDiscoveryOptions();
if (this.selectorOptions != null) {
this.selectorOptions.applyTo(result);
}
if (this.filterOptions != null) {
this.filterOptions.applyTo(result);View on GitHub (pinned to f070c699a0)