{"record":{"id":"286448983d4f7b50","repo":"theonedev/onedev","slug":"link-spec-is-not-multiple-and-source-issue-is-alre","errorCode":null,"errorMessage":"Link spec is not multiple and source issue is already linked to another issue via this link spec","messagePattern":"Link spec is not multiple and source issue is already linked to another issue via this link spec","errorType":"validation","errorClass":"ValidationException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/model/IssueLink.java","lineNumber":111,"sourceCode":"\t\t\t\t\t&& getSource().getTargetLinks().stream().anyMatch(it -> it.getSpec().equals(getSpec())))\n\t\t\t\tthrow new ValidationException(\n\t\t\t\t\t\t\"Link spec is not multiple and the source issue is already linked to another issue via this link spec\");\n\t\t\tif (!getSpec().getParsedIssueQuery(getSource().getProject()).matches(getTarget()))\n\t\t\t\tthrow new ValidationException(\"Link spec not allowed to link to the target issue\");\n\t\t\tif (!getSpec().getOpposite().isMultiple()\n\t\t\t\t\t&& getTarget().getSourceLinks().stream().anyMatch(it -> it.getSpec().equals(getSpec())))\n\t\t\t\tthrow new ValidationException(\n\t\t\t\t\t\t\"Opposite side of link spec is not multiple and the target issue is already linked to another issue via this link spec\");\n\t\t\tif (!getSpec().getOpposite().getParsedIssueQuery(getSource().getProject())\n\t\t\t\t\t.matches(getSource()))\n\t\t\t\tthrow new ValidationException(\"Opposite side of link spec not allowed to link to the source issue\");\n\t\t} else {\n\t\t\tif (getSource().getLinks().stream().anyMatch(it -> it.getSpec().equals(getSpec())\n\t\t\t\t\t&& it.getLinked(getSource()).equals(getTarget())))\n\t\t\t\tthrow new ValidationException(\"Specified issues already linked via specified link spec\");\n\t\t\tif (!getSpec().isMultiple()\n\t\t\t\t\t&& getSource().getLinks().stream().anyMatch(it -> it.getSpec().equals(getSpec())))\n\t\t\t\tthrow new ValidationException(\n\t\t\t\t\t\t\"Link spec is not multiple and source issue is already linked to another issue via this link spec\");\n\t\t\tvar parsedIssueQuery = getSpec().getParsedIssueQuery(getSource().getProject());\n\t\t\tif (!parsedIssueQuery.matches(getSource()) || !parsedIssueQuery.matches(getTarget()))\n\t\t\t\tthrow new ValidationException(\"Link spec not allowed to link specified issues\");\n\t\t}\n\t}\n}\n","sourceCodeStart":93,"sourceCodeEnd":119,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/model/IssueLink.java#L93-L119","documentation":"For a unidirectional link spec (no opposite) with isMultiple()==false, validate() limits the source issue to a single link of that spec. This is thrown when the source issue already has any link of the same spec (pointing at a different target than the one requested).","triggerScenarios":"createLink where getSpec().getOpposite() == null, getSpec().isMultiple() == false, and getSource().getLinks() contains any link with an equal spec.","commonSituations":"'Depends on' style spec defined as single-link; user tries to add a second dependency; automation linking a series of issues in a loop fails on the second link; spec changed to non-multiple while links existed.","solutions":["Unlink the source's existing link of this spec, then create the new one.","Enable 'Multiple' on the link spec if several links should be allowed.","Select a source issue without an existing link of this spec."],"exampleFix":"// before\nIssueLink.createLink(link); // single spec, src already linked\n// after\nIssueLink old = src.getLinks().stream().filter(l -> l.getSpec().equals(spec)).findFirst().orElse(null);\nif (old != null) old.remove();\nIssueLink.createLink(link);","handlingStrategy":"validation","validationCode":"boolean hasLink = source.getLinks().stream().anyMatch(l -> l.getSpec().equals(spec));\nif (!spec.isMultiple() && hasLink) { /* unlink old link first or abort */ }","typeGuard":null,"tryCatchPattern":"try { IssueLink.createLink(link); } catch (ValidationException e) { // replace existing single link then retry }","preventionTips":["Enable Multiple when an issue may hold several links of a spec","Replace-not-add semantics for single-capacity specs","Audit existing links before bulk link operations"],"tags":["issue-links","validation","multiplicity"],"backgroundTag":"invalid-state-transition","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}