getgrav/grav · warning · RuntimeException
Failed: Cannot set page parent to a child of current page
Error message
Failed: Cannot set page parent to a child of current page
What it means
The second guard in FlexPageObject::move() rejects moving a page under its own descendant: Utils::startsWith($parent->rawRoute(), $this->rawRoute()) detects that the target parent's route is prefixed by the current page's route, which would create a cycle in the page tree. The operation is aborted before any state changes (storeOriginal() runs only after both checks).
Source
Thrown at system/src/Grav/Framework/Flex/Pages/Traits/PageLegacyTrait.php:279
throw new RuntimeException(__METHOD__ . '(): Not Implemented');
}
/**
* Prepare move page to new location. Moves also everything that's under the current page.
*
* You need to call $this->save() in order to perform the move.
*
* @param PageInterface $parent New parent page.
* @return $this
*/
public function move(PageInterface $parent)
{
if ($this->route() === $parent->route()) {
throw new RuntimeException('Failed: Cannot set page parent to self');
}
$rawRoute = $this->rawRoute();
if ($rawRoute && Utils::startsWith($parent->rawRoute(), $rawRoute)) {
throw new RuntimeException('Failed: Cannot set page parent to a child of current page');
}
$this->storeOriginal();
// TODO:
throw new RuntimeException(__METHOD__ . '(): Not Implemented');
}
/**
* Prepare a copy from the page. Copies also everything that's under the current page.
*
* Returns a new Page object for the copy.
* You need to call $this->save() in order to perform the move.
*
* @param PageInterface|null $parent New parent page.
* @return $this
*/
public function copy(?PageInterface $parent = null)View on GitHub (pinned to 6040efed04)
Solutions
- Verify direction before moving: reject when str_starts_with($parent->rawRoute(), $page->rawRoute()) in your own UI logic.
- When moving a whole branch, pass the new parent from outside the branch only.
- Fix argument order if the intended operation was moving the child under the page.
Example fix
// before
$ancestor->move($descendant); // inverted / cyclic
// after
if (!str_starts_with($descendant->rawRoute(), $ancestor->rawRoute())) {
$ancestor->move($descendant);
} Defensive patterns
Strategy: validation
Validate before calling
// Block moving a page into its own subtree (descendant check)
$rawRoute = $page->rawRoute();
if ($rawRoute && !str_starts_with($parent->rawRoute(), $rawRoute)) {
$page->move($parent);
$page->save();
} Try / catch
try {
$page->move($parent);
} catch (\Grav\Framework\Flex\Exception\RuntimeException $e) {
if (str_contains($e->getMessage(), 'child of current page')) {
$ui->setError('Cannot move a page under one of its own children.');
return;
}
throw $e;
} Prevention
- Filter the candidate parent list to routes outside the page's own subtree.
- Keep argument order straight: move($newParent) moves THIS page under $newParent.
- Never mutate and walk the page tree in the same pass during restructuring.
When it happens
Trigger: Calling $parentPage->move($childPage) with inverted arguments; picking a grandchild as the new parent in a move UI; programmatic re-parenting computed from a flattened route list where a descendant is selected.
Common situations: Admin tree drag-and-drop implemented via move() that allows dropping a branch into itself; automated restructuring scripts that walk the tree while mutating it.
Related errors
- Failed: Cannot set page parent to self
- Grav\Framework\Flex\Pages\Traits\PageLegacyTrait::init(): No
- Grav\Framework\Flex\Pages\Traits\PageLegacyTrait::raw(string
- Grav\Framework\Flex\Pages\Traits\PageLegacyTrait::file(): No
- No backups defined...
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/0b6189ab144fb2f3.
Report an issue: GitHub.