{"record":{"id":"58709c866eeae19e","repo":"theonedev/onedev","slug":"not-authorized-to-create-root-project","errorCode":null,"errorMessage":"Not authorized to create root project","messagePattern":"Not authorized to create root project","errorType":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/ProjectResource.java","lineNumber":359,"sourceCode":"\t\t\tcheckProjectCreationPermission(subject, parent);\n\n\t\tif (parent != null && project.isSelfOrAncestorOf(parent))\n\t\t\tthrow new ExplicitException(\"Cannot use current or descendant project as parent\");\n\n\t\tcheckProjectNameDuplication(project);\n\n\t\tprojectService.update(project);\n\t\tauditService.audit(project, \"changed project via RESTful API\", oldAuditContent,\n\t\t\t\tVersionedXmlDoc.fromBean(ProjectData.from(project)).toXML());\n\n\t\treturn Response.ok().build();\n\t}\n\t\n\tprivate void checkProjectCreationPermission(Subject subject, @Nullable Project parent) {\n\t\tif (parent != null && !SecurityUtils.canCreateChildren(subject, parent))\n\t\t\tthrow new UnauthorizedException(\"Not authorized to create project under '\" + parent.getPath() + \"'\");\n\t\tif (parent == null && !SecurityUtils.canCreateRootProjects(subject))\n\t\t\tthrow new UnauthorizedException(\"Not authorized to create root project\");\n\t}\n\t\n\tprivate void checkProjectNameDuplication(Project project) {\n\t\tProject parent = project.getParent();\n\t\tProject projectWithSameName = projectService.find(parent, project.getName());\n\t\tif (projectWithSameName != null && !projectWithSameName.equals(project)) {\n\t\t\tif (parent != null) {\n\t\t\t\tthrow new ExplicitException(\"Name '\" + project.getName() + \"' is already used by another project under '\"\n\t\t\t\t\t\t+ parent.getPath() + \"'\");\n\t\t\t} else {\n\t\t\t\tthrow new ExplicitException(\"Name '\" + project.getName() + \"' is already used by another root project\");\n\t\t\t}\n\t\t}\n\t}\n\t\n\t@Api(order=900, description=\"Update project settings\")\n\t@Path(\"/{projectId}/setting\")\n    @POST","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/ProjectResource.java#L341-L377","documentation":"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.","triggerScenarios":"POST /rest/projects with no parent, or an update changing parentId to null (moving to root), by a user without root-project creation permission.","commonSituations":"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.","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"],"exampleFix":"// before\nPOST /rest/projects {\"name\":\"myproj\"} // parent null, no root permission\n// after\nPOST /rest/projects {\"name\":\"myproj\",\"parent\":{\"path\":\"allowed-parent\"}}","handlingStrategy":"validation","validationCode":"// only attempt root creation if the account is allowed\nif (parentId == null && !userCanCreateRootProjects(currentUser)) {\n  throw new Error('account cannot create root projects; supply a parent');\n}","typeGuard":"const isRootCreation = (payload) => payload.parent == null && payload.parentId == null;","tryCatchPattern":"try {\n  await api.post('/rest/projects', payload);\n} catch (e) {\n  if (e.status === 401 && /root project/.test(e.message)) {\n    payload.parent = {path: 'default-parent'}; // fall back to allowed parent\n  } else throw e;\n}","preventionTips":["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"],"tags":["rest","authorization","project-hierarchy"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}