theonedev/onedev · error · UnauthorizedException
Not authorized
Error message
Not authorized
What it means
The mergePullRequest endpoint checks SecurityUtils.canWriteCode(user.asSubject(), pullRequest.getProject()); if the authenticated user lacks code write permission on the PR's project, an UnauthorizedException ('Not authorized') is thrown before the merge is performed.
Source
Thrown at server-core/src/main/java/io/onedev/server/ai/TodResource.java:1503
return PullRequestHelper.getDetail(currentProject, pullRequest);
}
@Path("/merge-pull-request")
@Consumes(MediaType.TEXT_PLAIN)
@POST
public Map<String, Object> mergePullRequest(
@QueryParam("currentProject") @NotNull String currentProjectPath,
@QueryParam("reference") @NotNull String pullRequestReference,
String commitMessage) {
var user = SecurityUtils.getUser();
if (user == null)
throw new UnauthenticatedException();
var currentProject = getProject(currentProjectPath);
var pullRequest = getPullRequest(currentProject, pullRequestReference);
if (!SecurityUtils.canWriteCode(user.asSubject(), pullRequest.getProject()))
throw new UnauthorizedException();
commitMessage = trimToNull(commitMessage);
pullRequestService.merge(user, pullRequest, commitMessage);
return PullRequestHelper.getDetail(currentProject, pullRequest);
}
@Path("/discard-pull-request")
@Consumes(MediaType.TEXT_PLAIN)
@POST
public Map<String, Object> discardPullRequest(
@QueryParam("currentProject") @NotNull String currentProjectPath,
@QueryParam("reference") @NotNull String pullRequestReference,
String comment) {
var user = SecurityUtils.getUser();
if (user == null)
throw new UnauthenticatedException();View on GitHub (pinned to d44925c47c)
Solutions
- Grant the user or token's role code write permission on the PR's project in OneDev security settings.
- Use a token/account that has write access to the target project.
- Verify the correct project — permission is evaluated against the PR's own project, not currentProject.
Example fix
// before // token user has only 'Read' role on project mergePullRequest(ref) // after // Admin: Project -> Security -> give role 'Code Write', or use an account with write access mergePullRequest(ref)
Defensive patterns
Strategy: validation
Validate before calling
const me = await getCurrentUser()
if (!canWriteCode(me, pr.project)) throw new Error(`user ${me.name} lacks code write permission on ${pr.project}`) Type guard
function canMerge(user, project) { return Boolean(user?.permissions?.[project]?.includes('WRITE_CODE')) } Try / catch
try { await mergePullRequest(ref) }
catch (e) { if (/not authorized|unauthorized/i.test(e.message)) { throw new Error(`Grant code write permission on the PR's project before merging: ${e.message}`) } else throw e } Prevention
- Verify the account/token role has Code Write on the PR's project
- Remember permission is checked against pullRequest.getProject(), not the currentProject param
- Use a dedicated bot account with the required role for merges
When it happens
Trigger: Calling POST /merge-pull-request as an authenticated user whose effective permissions on the project do not include code write (e.g. read-only role, guest access, or the PR belongs to a project the user cannot push to).
Common situations: Bot/API token scoped to a role without write access; user moved to a read-only group; PR lives in a different project than assumed and permission is checked against pullRequest.getProject().
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
- Pull request is closed
- errorMessage (from checkMergeCondition)
- Error checking merge commit message: ${errorMessage}
- Reviewer not found:
- Pull request submitter cannot be reviewer
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/d135e78585d90b2d.
Report an issue: GitHub.