{"record":{"id":"1597ed8f5ca600c0","repo":"theonedev/onedev","slug":"link-spec-not-allowed-to-link-specified-issues","errorCode":null,"errorMessage":"Link spec not allowed to link specified issues","messagePattern":"Link spec not allowed to link specified issues","errorType":"validation","errorClass":"ValidationException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/model/IssueLink.java","lineNumber":115,"sourceCode":"\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":97,"sourceCodeEnd":119,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/model/IssueLink.java#L97-L119","documentation":"For a unidirectional link spec, validate() applies the spec's issue query to BOTH ends: the link is rejected unless parsedIssueQuery matches both the source and the target issue. This error is thrown when either endpoint fails the spec's query.","triggerScenarios":"createLink where the spec (opposite == null) defines an issue query and !query.matches(source) || !query.matches(target) in the source project.","commonSituations":"Spec restricted to certain issue types/states (e.g. only 'Task' issues may be linked) and one endpoint violates it; issues in projects whose fields don't satisfy the query; stale UI showing an allowed pair after the query changed.","solutions":["Change the non-matching issue's state/type/fields so it satisfies the spec's query.","Update the link spec's issue query to permit the intended issues.","Pick issues matching the query or a different link spec."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var q = spec.getParsedIssueQuery(source.getProject());\nif (!q.matches(source) || !q.matches(target)) throw new IllegalStateException(\"both issues must match spec query\");","typeGuard":null,"tryCatchPattern":"try { IssueLink.createLink(link); } catch (ValidationException e) { // report that the spec's issue query rejects one endpoint }","preventionTips":["Check both endpoints against the spec query before linking","Keep spec queries permissive enough for intended workflows","Re-validate links after changing issue types/states"],"tags":["issue-links","issue-query","validation"],"backgroundTag":"invalid-argument-value","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"}