{"record":{"id":"433e0055b35f4374","repo":"theonedev/onedev","slug":"cannot-use-current-or-descendant-project-as-parent","errorCode":null,"errorMessage":"Cannot use current or descendant project as parent","messagePattern":"Cannot use current or descendant project as parent","errorType":"http","errorClass":"NotAcceptableException","httpStatus":406,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/ProjectResource.java","lineNumber":292,"sourceCode":"\t\n\t@SuppressWarnings(\"unused\")\n\tprivate static String getDateExample() {\n\t\treturn DateUtils.formatISO8601Date(new Date());\n\t}\n\t\n\t@Api(order=800, description=\"Create new project\")\n    @POST\n    public Long createProject(@NotNull @Valid ProjectData data) {\n\t\tvar project = new Project();\n\t\tdata.populate(project, projectService);\n\t\t\n\t\tvar subject = SecurityUtils.getSubject();\n\t\tvar user = SecurityUtils.getUser(subject);\n\n\t\tcheckProjectCreationPermission(subject, project.getParent());\n\t\n\t\tif (project.getParent() != null && project.isSelfOrAncestorOf(project.getParent())) \n\t\t\tthrow new NotAcceptableException(\"Cannot use current or descendant project as parent\");\n\t\t\n\t\tcheckProjectNameDuplication(project);\t\t\n\n\t\tif (project.getForkedFrom() != null) {\n\t\t\tvar forkedFrom = project.getForkedFrom();\n\t\t\tif (!SecurityUtils.canReadCode(subject, forkedFrom))\n\t\t\t\tthrow new UnauthorizedException(\"Not authorized to read code of project '\" + forkedFrom.getPath() + \"'\");\n\t\t\tproject.getBuildSetting().setBuildPreservations(forkedFrom.getBuildSetting().getBuildPreservations());\n\t\t\tproject.getBuildSetting().setCachePreserveDays(forkedFrom.getBuildSetting().getCachePreserveDays());\n\t\t\tproject.getBuildSetting().setJobProperties(forkedFrom.getBuildSetting().getJobProperties());\n\t\t\tproject.getBuildSetting().setDefaultFixedIssueFilters(forkedFrom.getBuildSetting().getDefaultFixedIssueFilters());\n\t\t\tproject.getBuildSetting().setListParams(forkedFrom.getBuildSetting().getListParams(false));\n\t\t\tproject.getBuildSetting().setNamedQueries(forkedFrom.getBuildSetting().getNamedQueries());\n\t\t\tproject.setPackSetting(forkedFrom.getPackSetting());\n\t\t\tproject.setPullRequestSetting(forkedFrom.getPullRequestSetting());\n\t\t\tproject.setWorkspaceSetting(forkedFrom.getWorkspaceSetting());\n\t\t\tproject.setNamedCommitQueries(forkedFrom.getNamedCommitQueries());\n\t\t\tproject.setIssueSetting(forkedFrom.getIssueSetting());","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/ProjectResource.java#L274-L310","documentation":"createProject rejects a parent project that is the new project's own subtree: NotAcceptableException 'Cannot use current or descendant project as parent'. Project hierarchy must remain a tree; parenting a project under itself or one of its descendants would create a cycle.","triggerScenarios":"POST /rest/projects with a Project whose parent (or parentId) points to a project for which project.isSelfOrAncestorOf(parent) is true — i.e. parent is the same project or a project nested below it. Mainly occurs when copying an existing project's data (e.g. forking/synchronizing) where parent fields are carried along.","commonSituations":"Cloning a project payload from an existing subproject and re-posting it without clearing/changing parent; automation that derives parent from the source project; importing projects in bulk with stale hierarchy data.","solutions":["Set parent to a different, existing ancestor-level project (or null for a root project)","When copying a project payload, explicitly clear parent/parentId before POSTing","If the intent was a fork, set forkedFrom instead of parent"],"exampleFix":"// before\nproject.setParent(sourceProject); // source is inside new project's subtree\n// after\nProject parent = projectService.find(\"root-team\");\nproject.setParent(Objects.equals(parent, project) ? null : parent);","handlingStrategy":"validation","validationCode":"// before POST, ensure parent is not within the new project's subtree\nif (parent && (parent.id === project.id || descendantIdsOf(project).includes(parent.id))) {\n  throw new Error('parent must not be the project itself or a descendant');\n}","typeGuard":"function safeParent(project, parent) { return parent == null || !isSelfOrAncestorOf(project, parent) ? parent : null; }","tryCatchPattern":"try {\n  const created = await api.post('/rest/projects', payload);\n} catch (e) {\n  if (/descendant project as parent/.test(e.message)) {\n    payload.parent = null; // or pick another parent, then retry once\n  } else throw e;\n}","preventionTips":["Clear parent fields when copying project payloads","Model hierarchy moves explicitly, never copy source parent","Keep a client-side map of project paths to detect subtree relationships","Distinguish forkedFrom from parent in automation code"],"tags":["rest","project-hierarchy","validation"],"backgroundTag":"invalid-state-transition","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"}