theonedev/onedev · error · UnauthorizedException
Not authorized to create root project
Error message
Not authorized to create root project
What it means
checkProjectCreationPermission throws UnauthorizedException 'Not authorized to create root project' when parent is null and the subject lacks canCreateRootProjects. This restricts who can add top-level projects in OneDev.
Source
Thrown at server-core/src/main/java/io/onedev/server/rest/resource/ProjectResource.java:359
checkProjectCreationPermission(subject, parent);
if (parent != null && project.isSelfOrAncestorOf(parent))
throw new ExplicitException("Cannot use current or descendant project as parent");
checkProjectNameDuplication(project);
projectService.update(project);
auditService.audit(project, "changed project via RESTful API", oldAuditContent,
VersionedXmlDoc.fromBean(ProjectData.from(project)).toXML());
return Response.ok().build();
}
private void checkProjectCreationPermission(Subject subject, @Nullable Project parent) {
if (parent != null && !SecurityUtils.canCreateChildren(subject, parent))
throw new UnauthorizedException("Not authorized to create project under '" + parent.getPath() + "'");
if (parent == null && !SecurityUtils.canCreateRootProjects(subject))
throw new UnauthorizedException("Not authorized to create root project");
}
private void checkProjectNameDuplication(Project project) {
Project parent = project.getParent();
Project projectWithSameName = projectService.find(parent, project.getName());
if (projectWithSameName != null && !projectWithSameName.equals(project)) {
if (parent != null) {
throw new ExplicitException("Name '" + project.getName() + "' is already used by another project under '"
+ parent.getPath() + "'");
} else {
throw new ExplicitException("Name '" + project.getName() + "' is already used by another root project");
}
}
}
@Api(order=900, description="Update project settings")
@Path("/{projectId}/setting")
@POSTView on GitHub (pinned to d44925c47c)
Solutions
- Grant the account permission to create root projects (server security setting / admin role)
- Specify an allowed parent project instead of creating a root project
- Use an admin or dedicated service account with root-project creation rights
Example fix
// before
POST /rest/projects {"name":"myproj"} // parent null, no root permission
// after
POST /rest/projects {"name":"myproj","parent":{"path":"allowed-parent"}} Defensive patterns
Strategy: validation
Validate before calling
// only attempt root creation if the account is allowed
if (parentId == null && !userCanCreateRootProjects(currentUser)) {
throw new Error('account cannot create root projects; supply a parent');
} Type guard
const isRootCreation = (payload) => payload.parent == null && payload.parentId == null;
Try / catch
try {
await api.post('/rest/projects', payload);
} catch (e) {
if (e.status === 401 && /root project/.test(e.message)) {
payload.parent = {path: 'default-parent'}; // fall back to allowed parent
} else throw e;
} Prevention
- Always specify an allowed parent unless root creation is intended
- Document which accounts may create root projects
- Update automation after policy changes restricting root creation
- Prefer explicit parent paths over omitted fields in payloads
When it happens
Trigger: POST /rest/projects with no parent, or an update changing parentId to null (moving to root), by a user without root-project creation permission.
Common situations: Regular users POSTing projects without a parent field; automation moving projects to root; permission model changes making root creation admin-only after the client was written.
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
- Not authorized to create project under '${parent.path}'
- No permission to access issue: ${referenceString}
- No permission to write code in issue project
- Code write permission is required to edit auto merge
- Not authorized
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/58709c866eeae19e.
Report an issue: GitHub.