{"record":{"id":"9df32e21404385b0","repo":"theonedev/onedev","slug":"duplicate-values-not-allowed","errorCode":null,"errorMessage":"Duplicate values not allowed","messagePattern":"Duplicate values not allowed","errorType":"validation","errorClass":"ValidationException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/buildspec/param/ParamUtils.java","lineNumber":38,"sourceCode":"import org.jspecify.annotations.Nullable;\nimport javax.validation.ValidationException;\nimport java.io.Serializable;\nimport java.util.*;\nimport java.util.stream.Collectors;\n\npublic class ParamUtils {\n\t\n\tprivate static final Logger logger = LoggerFactory.getLogger(ParamInstances.class);\n\t\n\tprivate static final String PARAM_BEAN_CLASS_NAME_PREFIX = \"BuildParamBean\";\n\t\n\tpublic static void validateParamValues(List<List<String>> values) {\n\t\tif (values.isEmpty())\n\t\t\tthrow new ValidationException(\"At least one value needs to be specified\");\n\t\tSet<List<String>> encountered = new HashSet<>();\n\t\tfor (List<String> value: values) {\n\t\t\tif (encountered.contains(value)) \n\t\t\t\tthrow new ValidationException(\"Duplicate values not allowed\");\n\t\t\telse \n\t\t\t\tencountered.add(value);\n\t\t}\n\t}\n\t\n\tprivate static void validateParamMatrix(List<ParamSpec> paramSpecs, Map<String, List<List<String>>> paramMatrix) {\n\t\tMap<String, ParamSpec> paramSpecMap = ParamUtils.getParamSpecMap(paramSpecs);\n\t\tvalidateParamNames(paramSpecMap.keySet(), paramMatrix.keySet());\n\t\tfor (Map.Entry<String, List<List<String>>> entry: paramMatrix.entrySet()) {\n\t\t\tif (entry.getValue() != null) {\n\t\t\t\ttry {\n\t\t\t\t\tvalidateParamValues(entry.getValue());\n\t\t\t\t} catch (ValidationException e) {\n\t\t\t\t\tString errorMessage = String.format(\"Error validating param values (param: %s, error message: %s)\", \n\t\t\t\t\t\t\tentry.getKey(), e.getMessage());\n\t\t\t\t\tthrow new ValidationException(errorMessage);\n\t\t\t\t}\n\t\t\t\t","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/buildspec/param/ParamUtils.java#L20-L56","documentation":"Thrown by ParamUtils.validateParamValues when the same value combination (List<String>) appears more than once for a parameter. Duplicates are meaningless for a value matrix and would create ambiguous param instances, so validation rejects them. validateParamMatrix wraps this with the param name for context.","triggerScenarios":"Calling validateParamValues with a list containing two identical List<String> entries, e.g. values [[\"a\"],[\"a\"]], typically from SpecifiedValues in a BuildSpec.","commonSituations":"Copy-pasting a value row in the YAML or in the job parameter form; merging param lists from two sources; UI allowing repeated rows.","solutions":["Remove the duplicate value row so each combination is unique","If multiple params share values, use one row with multiple columns instead of repeated rows","Deduplicate programmatically before calling validateParamValues"],"exampleFix":"// before\nvalues: [[\"1.0\"], [\"1.0\"]]\n// after\nvalues: [[\"1.0\"], [\"2.0\"]]","handlingStrategy":"validation","validationCode":"Set<List<String>> seen = new HashSet<>();\nfor (List<String> row : values)\n    if (!seen.add(row)) throw new IllegalArgumentException(\"duplicate value combination: \" + row);","typeGuard":null,"tryCatchPattern":"try { ParamUtils.validateParamValues(values); } catch (ValidationException e) { /* deduplicate and retry */ }","preventionTips":["Deduplicate value rows before saving the buildspec","Avoid copy-pasting param blocks in YAML","Use a LinkedHashSet when building value lists programmatically"],"tags":["validation","buildspec","params"],"backgroundTag":"invalid-config-value","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}