theonedev/onedev · error · ValidationException
Source issue already linked to target issue via specified li
Error message
Source issue already linked to target issue via specified link spec
What it means
IssueLink.validate also rejects duplicate or conflicting links when the spec has an opposite (bidirectional) definition. If the source issue already has a link via this spec to the same target, ValidationException 'Source issue already linked to target issue via specified link spec' is thrown.
Source
Thrown at server-core/src/main/java/io/onedev/server/model/IssueLink.java:91
public Issue getLinked(Issue issue) {
return issue.equals(source)?target:source;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public void validate() {
if (getSource().equals(getTarget()))
throw new ValidationException("Cannot link to self");
if (getSpec().getOpposite() != null) {
if (getSource().getTargetLinks().stream()
.anyMatch(it -> it.getSpec().equals(getSpec()) && it.getTarget().equals(getTarget())))
throw new ValidationException("Source issue already linked to target issue via specified link spec");
if (!getSpec().isMultiple()
&& getSource().getTargetLinks().stream().anyMatch(it -> it.getSpec().equals(getSpec())))
throw new ValidationException(
"Link spec is not multiple and the source issue is already linked to another issue via this link spec");
if (!getSpec().getParsedIssueQuery(getSource().getProject()).matches(getTarget()))
throw new ValidationException("Link spec not allowed to link to the target issue");
if (!getSpec().getOpposite().isMultiple()
&& getTarget().getSourceLinks().stream().anyMatch(it -> it.getSpec().equals(getSpec())))
throw new ValidationException(
"Opposite side of link spec is not multiple and the target issue is already linked to another issue via this link spec");
if (!getSpec().getOpposite().getParsedIssueQuery(getSource().getProject())
.matches(getSource()))
throw new ValidationException("Opposite side of link spec not allowed to link to the source issue");
} else {
if (getSource().getLinks().stream().anyMatch(it -> it.getSpec().equals(getSpec())
&& it.getLinked(getSource()).equals(getTarget())))
throw new ValidationException("Specified issues already linked via specified link spec");
if (!getSpec().isMultiple()View on GitHub (pinned to d44925c47c)
Solutions
- Check for an existing link with the same spec and target before creating (query source.getTargetLinks())
- Make link creation idempotent in scripts by skipping existing pairs
- Fix double-submit in UI/automation (disable button, dedupe requests)
Example fix
// before issueLinkService.createLink(source, target, spec); // may duplicate // after boolean exists = source.getTargetLinks().stream().anyMatch(l -> l.getSpec().equals(spec) && l.getTarget().equals(target)); if (!exists) issueLinkService.createLink(source, target, spec);
Defensive patterns
Strategy: validation
Validate before calling
boolean exists = source.getTargetLinks().stream().anyMatch(l -> l.getSpec().equals(spec) && l.getTarget().equals(target));
Try / catch
try { createLink(source, target, spec); } catch (ValidationException e) { /* treat as already-linked, continue */ } Prevention
- Make link creation idempotent
- Check existing target links before creating
- Prevent double-submit in UI/automation
When it happens
Trigger: Calling createLink twice for the same source/target/spec pair; concurrent automation both creating the same link; retried import scripts re-running link creation.
Common situations: Idempotency issues in bulk import scripts; UI double-submit creating the link twice; automation that recreates links after issue edits without checking existing links.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot link to self
- Title is required
- Issue ${issueReference} is not in current project
- Invalid issue id/number
- Not eligible for multi-value
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/2c3dd436db0588e3.
Report an issue: GitHub.