theonedev/onedev · error · UnauthorizedException

No permission to add specified link for specified issues

Error message

No permission to add specified link for specified issues

What it means

Thrown as UnauthorizedException when the authenticated user lacks permission (SecurityUtils.canEditIssueLink) to create the specified link on either the source or the target issue's project. Both projects must permit editing this link type for the user.

Source

Thrown at server-core/src/main/java/io/onedev/server/ai/TodResource.java:726

    public Map<String, Object> linkIssues(
                @QueryParam("currentProject") @NotNull String currentProjectPath, 
                @QueryParam("sourceReference") @NotNull String sourceReference, 
                @QueryParam("linkName") @Nullable String linkName, 
                @QueryParam("targetReference") @NotNull String targetReference) {
        if (SecurityUtils.getUser() == null)
            throw new UnauthenticatedException();

        var currentProject = getProject(currentProjectPath);

        var sourceIssue = getIssue(currentProject, sourceReference);
        var targetIssue = getIssue(currentProject, targetReference);

        var linkSpec = linkSpecService.find(linkName);
        if (linkSpec == null)
            throw new NotFoundException("Link spec not found: " + linkName);
        if (!SecurityUtils.canEditIssueLink(sourceIssue.getProject(), linkSpec) 
                || !SecurityUtils.canEditIssueLink(targetIssue.getProject(), linkSpec)) {
            throw new UnauthorizedException("No permission to add specified link for specified issues");
        }
        
        var link = new IssueLink();
        link.setSpec(linkSpec);
        if (linkName.equals(linkSpec.getName())) {
            link.setSource(sourceIssue);
            link.setTarget(targetIssue);
        } else {
            link.setSource(targetIssue);
            link.setTarget(sourceIssue);
        }
        link.validate();
        issueLinkService.create(link);

        var linkMap = new HashMap<String, Object>();
        linkMap.put("source", link.getSource().getReference().toString(currentProject));
        linkMap.put("target", link.getTarget().getReference().toString(currentProject));
        linkMap.put("linkName", link.getSpec().getName());

View on GitHub (pinned to d44925c47c)

Solutions

  1. Grant the user permission to edit this issue link type in both projects (project role/permission settings).
  2. Use an identity with link-edit rights on both projects.
  3. Choose a link spec the user is authorized to use across both projects.

Example fix

// before
user without 'Edit Issue Link' on target project attempts link
// after: elevate the user's role in BOTH projects, or authenticate as a user
// with canEditIssueLink(sourceProject, spec) && canEditIssueLink(targetProject, spec)
Defensive patterns

Strategy: try-catch

Validate before calling

// check link-edit permission on both projects before linking
if (!canEditLink(user, sourceIssue.project, linkSpec) ||
    !canEditLink(user, targetIssue.project, linkSpec)) {
  throw new Error("User lacks link-edit permission on source or target project");
}

Type guard

function canLinkBoth(user, source, target, spec) {
  return hasPermission(user, source.project, `link:${spec.name}`)
      && hasPermission(user, target.project, `link:${spec.name}`);
}

Try / catch

try {
  await linkIssues(...);
} catch (e) {
  if (e.status === 401 || /No permission to add specified link/.test(e.message)) {
    // elevate identity or surface a permissions request to an admin
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the AI tod link-issues endpoint where canEditIssueLink fails for the source issue's project or the target issue's project for the given link spec.

Common situations: User can edit links in the source project but the target issue lives in a more restricted project; link spec has restricted authorization; low-privileged user or agent identity.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/2e90ea65ab8688b6. Report an issue: GitHub.