{"record":{"id":"357a5af267deb664","repo":"theonedev/onedev","slug":"not-authorized-to-create-root-project-357a5a","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/service/impl/DefaultProjectService.java","lineNumber":562,"sourceCode":"\t@Override\n\tpublic Project setup(Subject subject, String path) {\n\t\tList<String> names = Splitter.on(\"/\").omitEmptyStrings().trimResults().splitToList(path);\n\t\tProject project = null;\n\t\tfor (String name : names) {\n\t\t\tProject child;\n\t\t\tif (project == null || !project.isNew()) {\n\t\t\t\t// Query database directly instead of calling findByName to fix issue \n\t\t\t\t// #923 - Multi level projects after import and 1dev upgrade are mingled\n\t\t\t\tEntityCriteria<Project> criteria = EntityCriteria.of(Project.class);\n\t\t\t\tif (project != null)\n\t\t\t\t\tcriteria.add(Restrictions.eq(Project.PROP_PARENT, project));\n\t\t\t\telse\n\t\t\t\t\tcriteria.add(Restrictions.isNull(Project.PROP_PARENT));\n\t\t\t\tcriteria.add(Restrictions.eq(Project.PROP_NAME, name));\n\t\t\t\tchild = find(criteria);\n\t\t\t\tif (child == null) {\n\t\t\t\t\tif (project == null && !SecurityUtils.canCreateRootProjects(subject))\n\t\t\t\t\t\tthrow new UnauthorizedException(_T(\"Not authorized to create root project\"));\n\t\t\t\t\tif (project != null && !SecurityUtils.canCreateChildren(subject, project))\n\t\t\t\t\t\tthrow new UnauthorizedException(MessageFormat.format(_T(\"Not authorized to create project under \\\"{0}\\\"\"), project.getPath()));\n\t\t\t\t\tchild = new Project();\n\t\t\t\t\tchild.setName(name);\n\t\t\t\t\tchild.setParent(project);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tchild = new Project();\n\t\t\t\tchild.setName(name);\n\t\t\t\tchild.setParent(project);\n\t\t\t}\n\t\t\tproject = child;\n\t\t}\n\n\t\tProject parent = project.getParent();\n\t\twhile (parent != null && parent.isNew()) {\n\t\t\tparent.setCodeManagement(false);\n\t\t\tparent.setIssueManagement(false);","sourceCodeStart":544,"sourceCodeEnd":580,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/service/impl/DefaultProjectService.java#L544-L580","documentation":"OneDev throws this UnauthorizedException when a user attempts to create (or implicitly create via a nested path) a project at the repository root without having the 'Create Root Projects' permission. In DefaultProjectService.setup, when walking a project path, if no project with the given name exists and there is no parent project, the current Subject is checked with SecurityUtils.canCreateRootProjects; failing that check aborts the operation.","triggerScenarios":"Calling ProjectService.setup (e.g. via REST API POST /api/projects with a name, or push-to-create) where the resolved parent path is null (root-level project), the project does not already exist, and the authenticated subject lacks the 'Create Root Projects' privilege.","commonSituations":"A regular user (not a session/user with administrator or explicitly granted 'Create Root Projects') tries to create a top-level project via the REST API, CLI, or git push-to-create; CI jobs using a token whose owner lacks the permission attempt to provision a root project; an admin removed the permission but scripts still reference old behavior.","solutions":["Grant the user (or their group) the 'Create Root Projects' permission in OneDev security settings, or make the user an administrator.","Create the project under an existing parent project instead (path like parent/child), where 'Create Children' permission on the parent suffices.","Have an administrator create the root project and grant the user access to it.","If triggered by automation, use credentials of a service account that has the required permission."],"exampleFix":"// before\ncurl -X POST -u regularuser:pass -H 'Content-Type: application/json' \\\n  -d '{\"name\":\"myproject\"}' https://onedev.example.com/api/projects\n// after: create under a parent the user may write to\ncurl -X POST -u regularuser:pass -H 'Content-Type: application/json' \\\n  -d '{\"name\":\"team-space/myproject\"}' https://onedev.example.com/api/projects","handlingStrategy":"try-catch","validationCode":"// REST client pre-check: confirm the path is not root, or the user can create root projects\nvar path = projectName.contains(\"/\") ? projectName.substring(0, projectName.lastIndexOf('/')) : null;\nif (path == null && !isRootProjectCreator(user)) {\n    throw new IllegalStateException(\"User lacks 'Create Root Projects' permission\");\n}","typeGuard":"function canCreateRoot(user) {\n  return typeof user === 'object' && user !== null &&\n    Array.isArray(user.permissions) && user.permissions.includes('CREATE_ROOT_PROJECTS');\n}","tryCatchPattern":"try {\n    projectService.setup(subject, projectName);\n} catch (UnauthorizedException e) {\n    logger.warn(\"Project creation not permitted: {}\", e.getMessage());\n    // surface a permission request to the user or fall back to a permitted parent\n}","preventionTips":["Grant 'Create Root Projects' only to trusted roles; use nested projects under team namespaces for regular users","Check the user's effective permissions before automating project creation","Use service accounts with explicit, documented permissions for CI provisioning","Prefer creating projects under an existing parent where 'Create Children' is already granted"],"tags":["authorization","permissions","project-creation","onedev"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}