theonedev/onedev · error · UnauthorizedException

Not eligible to comment issue:

Error message

Not eligible to comment issue: 

What it means

For anonymous (unrecognized email sender) replies to an issue, OneDev only allows commenting if the sender address is already listed in the issue's external participants. Otherwise an UnauthorizedException 'Not eligible to comment issue: <ref>' is thrown.

Source

Thrown at server-core/src/main/java/io/onedev/server/mail/DefaultMailService.java:525

										bindings.put("issue", involvedIssue);

										String htmlBody = EmailTemplates.evalTemplate(true, template, bindings);
										String textBody = EmailTemplates.evalTemplate(false, template, bindings);

										var threadingReferences = getThreadingReferences(UUID.randomUUID().toString(), getMessageId(message));
										sendMailAsync(newArrayList(fromInternetAddress.getAddress()), newArrayList(), newArrayList(),
												subject, htmlBody, textBody, null, null, threadingReferences);
									} else {
										if (fromUser != null) {
											if (SecurityUtils.canAccessIssue(fromUser.asSubject(), involvedIssue))	
												addComment(involvedIssue, message, fromInternetAddress, fromUser, receiverInternetAddresses);
											else 
												throw new UnauthorizedException("No permission to comment issue: " + involvedIssue.getReference());
										} else {
											if (involvedIssue.getExternalParticipants().contains(fromInternetAddress)) 											
												addComment(involvedIssue, message, fromInternetAddress, null, receiverInternetAddresses);
											else
												throw new UnauthorizedException("Not eligible to comment issue: " + involvedIssue.getReference());
										}
									}
								} else if (subAddress.contains("pullrequest")) {
									if (fromUser != null) {
										involvedPullRequest = pullRequestService.get(entityId);
										if (involvedPullRequest == null)
											throw new ExplicitException("Non-existent pull request specified in recipient address: " + parsedReceiverAddress);
										if (subAddress.contains("unsubscribe")) {
											PullRequestWatch watch = pullRequestWatchService.find(involvedPullRequest, fromUser);
											if (watch != null) 
												watch.setWatching(false);
											
											String subject = "Unsubscribed successfully from pull request " + involvedPullRequest.getReference().toString(null);

											String template = StringUtils.join(settingService.getEmailTemplates().getPullRequestNotificationUnsubscribed(), "\n");
											Map<String, Object> bindings = new HashMap<>();
											bindings.put("pullRequest", involvedPullRequest);
											String htmlBody = EmailTemplates.evalTemplate(true, template, bindings);

View on GitHub (pinned to d44925c47c)

Solutions

  1. Reply from the original email address that participated in the issue.
  2. Have a project member add the address as an external participant, or enable service desk so anonymous senders can open issues.
  3. Comment through the web UI instead.

Example fix

// before
From: other@example.com (not an external participant of issue #42)
// after
From: original-reporter@example.com (in issue's external participants)
Defensive patterns

Strategy: validation

Validate before calling

if (fromUser == null && !issue.getExternalParticipants().contains(fromAddress))
    throw new UnauthorizedException("Not eligible to comment issue: " + issue.getReference());

Try / catch

try { handleMessage(message); } catch (UnauthorizedException e) { bounceToSender(e.getMessage()); }

Prevention

When it happens

Trigger: Email reply to issue~<id>~comment where fromUser is null and the From address is not in involvedIssue.getExternalParticipants().

Common situations: External reporter emails from a different address than the one used originally; someone uninvolved discovers the issue address and tries to reply; forwarding the thread from another mailbox.

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/cb9a4c17e0e2de43. Report an issue: GitHub.