{"record":{"id":"60527c2871af8b32","repo":"BookStackApp/BookStack","slug":"book-or-chapter-to-move-page-into-not-found","errorCode":null,"errorMessage":"Book or chapter to move page into not found","messagePattern":"Book or chapter to move page into not found","errorType":"exception","errorClass":"MoveOperationException","httpStatus":null,"severity":"error","filePath":"app/Entities/Repos/PageRepo.php","lineNumber":279,"sourceCode":"\n        $this->baseRepo->sortParent($page);\n\n        return $page;\n    }\n\n    /**\n     * Move the given page into a new parent book or chapter.\n     * The $parentIdentifier must be a string of the following format:\n     * 'book:<id>' (book:5).\n     *\n     * @throws MoveOperationException\n     * @throws PermissionsException\n     */\n    public function move(Page $page, string $parentIdentifier): Entity\n    {\n        $parent = $this->entityQueries->findVisibleByStringIdentifier($parentIdentifier);\n        if (!$parent instanceof Chapter && !$parent instanceof Book) {\n            throw new MoveOperationException('Book or chapter to move page into not found');\n        }\n\n        if (!userCan(Permission::PageCreate, $parent)) {\n            throw new PermissionsException('User does not have permission to create a page within the new parent');\n        }\n\n        return (new DatabaseTransaction(function () use ($page, $parent) {\n            $page->chapter_id = ($parent instanceof Chapter) ? $parent->id : null;\n            $newBookId = ($parent instanceof Chapter) ? $parent->book->id : $parent->id;\n            $this->parentChanger->changeBook($page, $newBookId);\n            $page->rebuildPermissions();\n\n            Activity::add(ActivityType::PAGE_MOVE, $page);\n\n            $this->baseRepo->sortParent($page);\n\n            return $parent;\n        }))->run();","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Entities/Repos/PageRepo.php#L261-L297","documentation":"PageRepo::move resolves the destination via findVisibleByStringIdentifier; pages may be moved into a Chapter or a Book. If the resolved entity is neither (missing, invisible, a Shelf, or another Page), it throws MoveOperationException('Book or chapter to move page into not found').","triggerScenarios":"move($page, $parentIdentifier) with a nonexistent identifier, a Shelf or Page ID, a soft-deleted parent, or an identifier for an entity the user cannot view (lookup returns null).","commonSituations":"Bulk-migration scripts referencing IDs from another environment; passing a shelf ID assuming pages can live on shelves; target chapter deleted before the move; permission restrictions hiding the target so it resolves to null.","solutions":["Confirm the identifier refers to an existing, visible Book or Chapter (fetch it first and check the type).","Don't pass Shelf or Page identifiers — resolve the chapter/book the page should live in.","Check the target isn't in the trash and the user has view permission on it.","Catch MoveOperationException around move() and prompt the user to pick a valid parent."],"exampleFix":"// before\n$pageRepo->move($page, $shelfId); // shelves are not valid page parents\n// after\n$parent = $entityQueries->findVisibleByStringIdentifier($parentId);\nif ($parent instanceof Book || $parent instanceof Chapter) {\n    $pageRepo->move($page, $parentId);\n}","handlingStrategy":"validation","validationCode":"$parent = $entityQueries->findVisibleByStringIdentifier($identifier);\nif (!($parent instanceof \\BookStack\\Entities\\Book || $parent instanceof \\BookStack\\Entities\\Chapter)) {\n    throw new \\InvalidArgumentException('Parent must be a Book or Chapter');\n}","typeGuard":"function isValidPageParent(?object $e): bool {\n    return $e instanceof \\BookStack\\Entities\\Book || $e instanceof \\BookStack\\Entities\\Chapter;\n}","tryCatchPattern":"try {\n    $pageRepo->move($page, $identifier);\n} catch (\\BookStack\\Exceptions\\MoveOperationException $e) {\n    return back()->withErrors(['parent' => $e->getMessage()]);\n}","preventionTips":["Never use Shelf or Page identifiers as page parents","Verify the parent exists and is visible to the acting user","Check trash/deletion status of the parent before bulk moves"],"tags":["bookstack","move-operation","validation","laravel"],"backgroundTag":"invalid-parent-entity","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}