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
- Reply from the original email address that participated in the issue.
- Have a project member add the address as an external participant, or enable service desk so anonymous senders can open issues.
- 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
- Reply from the original participant address
- Enable service desk for anonymous participation
- Keep the same mailbox for the whole thread
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
- No permission to comment issue:
- Code read permission required for project: %s
- Access denied
- Issue schedule permission required to set own estimated time
- Issue schedule permission required to set iterations
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/cb9a4c17e0e2de43.
Report an issue: GitHub.