theonedev/onedev · error · NotAcceptableException
Cannot use current or descendant project as parent
Error message
Cannot use current or descendant project as parent
What it means
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.
Source
Thrown at server-core/src/main/java/io/onedev/server/rest/resource/ProjectResource.java:292
@SuppressWarnings("unused")
private static String getDateExample() {
return DateUtils.formatISO8601Date(new Date());
}
@Api(order=800, description="Create new project")
@POST
public Long createProject(@NotNull @Valid ProjectData data) {
var project = new Project();
data.populate(project, projectService);
var subject = SecurityUtils.getSubject();
var user = SecurityUtils.getUser(subject);
checkProjectCreationPermission(subject, project.getParent());
if (project.getParent() != null && project.isSelfOrAncestorOf(project.getParent()))
throw new NotAcceptableException("Cannot use current or descendant project as parent");
checkProjectNameDuplication(project);
if (project.getForkedFrom() != null) {
var forkedFrom = project.getForkedFrom();
if (!SecurityUtils.canReadCode(subject, forkedFrom))
throw new UnauthorizedException("Not authorized to read code of project '" + forkedFrom.getPath() + "'");
project.getBuildSetting().setBuildPreservations(forkedFrom.getBuildSetting().getBuildPreservations());
project.getBuildSetting().setCachePreserveDays(forkedFrom.getBuildSetting().getCachePreserveDays());
project.getBuildSetting().setJobProperties(forkedFrom.getBuildSetting().getJobProperties());
project.getBuildSetting().setDefaultFixedIssueFilters(forkedFrom.getBuildSetting().getDefaultFixedIssueFilters());
project.getBuildSetting().setListParams(forkedFrom.getBuildSetting().getListParams(false));
project.getBuildSetting().setNamedQueries(forkedFrom.getBuildSetting().getNamedQueries());
project.setPackSetting(forkedFrom.getPackSetting());
project.setPullRequestSetting(forkedFrom.getPullRequestSetting());
project.setWorkspaceSetting(forkedFrom.getWorkspaceSetting());
project.setNamedCommitQueries(forkedFrom.getNamedCommitQueries());
project.setIssueSetting(forkedFrom.getIssueSetting());View on GitHub (pinned to d44925c47c)
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
Example fix
// before
project.setParent(sourceProject); // source is inside new project's subtree
// after
Project parent = projectService.find("root-team");
project.setParent(Objects.equals(parent, project) ? null : parent); Defensive patterns
Strategy: validation
Validate before calling
// before POST, ensure parent is not within the new project's subtree
if (parent && (parent.id === project.id || descendantIdsOf(project).includes(parent.id))) {
throw new Error('parent must not be the project itself or a descendant');
} Type guard
function safeParent(project, parent) { return parent == null || !isSelfOrAncestorOf(project, parent) ? parent : null; } Try / catch
try {
const created = await api.post('/rest/projects', payload);
} catch (e) {
if (/descendant project as parent/.test(e.message)) {
payload.parent = null; // or pick another parent, then retry once
} else throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Count should not be greater than ${RestConstants.MAX_PAGE_SI
- Count should not be greater than
- Unexpected query params:
- Invalid artifact path
- Count should not be greater than 1000
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/433e0055b35f4374.
Report an issue: GitHub.