theonedev/onedev · warning · UnauthorizedException
Permission denied
Error message
Permission denied
What it means
BoardColumnPanel's card drag/drop AJAX handler performs the same server-side authorization as the backlog panel: if canManageIssues(getProject()) is false for the current user it throws UnauthorizedException('Permission denied'). The check runs before any issue mutation from the POST parameters.
Source
Thrown at server-core/src/main/java/io/onedev/server/web/page/project/issues/boards/BoardColumnPanel.java:366
@Override
protected void onConfigure() {
super.onConfigure();
setVisible(getQuery() != null
&& SecurityUtils.getAuthUser() != null
&& (!getBoard().getIdentifyField().equals(Issue.NAME_STATE)
|| getColumn().equals(getIssueSetting().getInitialStateSpec().getName())));
}
});
head.add(countLabel = new Label("count", countModel).setOutputMarkupId(true));
add(ajaxBehavior = new AbstractPostAjaxBehavior() {
@Override
protected void respond(AjaxRequestTarget target) {
if (!canManageIssues(getProject()))
throw new UnauthorizedException(_T("Permission denied"));
IRequestParameters params = RequestCycle.get().getRequest().getPostParameters();
var issueId = params.getParameterValue("issueId").toLong();
var cardIndex = params.getParameterValue("cardIndex").toInt();
var card = cardListPanel.findCard(issueId);
if (card != null) { // Move in same column
cardListPanel.onCardDropped(target, issueId, cardIndex, true);
} else {
var subject = SecurityUtils.getSubject();
var user = SecurityUtils.getUser(subject);
Issue issue = getIssueService().load(issueId);
String fieldName = getBoard().getIdentifyField();
var iteration = getIterationSelection().getIteration();
if (iteration != null && !issue.getIterations().contains(iteration)) {
getIssueChangeService().addSchedule(user, issue, iteration);
cardListPanel.onCardDropped(target, issueId, cardIndex, true);
} else if (fieldName.equals(Issue.NAME_STATE)) {
AtomicReference<ManualSpec> transitionRef = new AtomicReference<>(null);View on GitHub (pinned to d44925c47c)
Solutions
- Assign the user/group a role with issue-management permission in the project's security settings.
- Re-login (or reload the page) after permission changes so the subject picks up new roles.
- Verify the board is in a project the user actually has edit rights on; move the board/work to an accessible project otherwise.
Defensive patterns
Strategy: try-catch
Validate before calling
if (!SecurityUtils.canManageIssues(project)) { /* disable card drag in UI */ } Try / catch
try { /* perform card move */ } catch (UnauthorizedException e) { notifyUser("Permission denied: ask for issue-management rights on this project"); } Prevention
- Check project authorization settings for the affected user/group.
- Reload the board page after permission updates.
- Do not replay board AJAX endpoints from scripts without proper permissions.
When it happens
Trigger: AJAX card move/drop (issueId/cardIndex POST) on a board column by a user lacking issue-management permission on the project.
Common situations: Read-only reporters/viewers attempting to reorder board cards; expired permission after role change while board page remains open; automated clients replaying board requests.
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
- Permission denied
- Access denied
- Issue schedule permission required to set iterations
- No permission to update issue fields
- No applicable manual transition spec found for current user
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/911bdb08a442fd57.
Report an issue: GitHub.