{"record":{"id":"0b4bcc93e8579ee3","repo":"BookStackApp/BookStack","slug":"this-page-is-already-published-or-does-not-belong","errorCode":null,"errorMessage":"This page is already published or does not belong to you.","messagePattern":"This page is already published or does not belong to you\\.","errorType":"exception","errorClass":"PermissionsException","httpStatus":null,"severity":"error","filePath":"app/Entities/Controllers/PageController.php","lineNumber":487,"sourceCode":"            return redirect($page->getUrl('/copy'));\n        }\n\n        $this->checkOwnablePermission(Permission::PageCreate, $newParent);\n\n        $newName = $request->input('name') ?: $page->name;\n        $pageCopy = $cloner->clonePage($page, $newParent, $newName);\n        $this->showSuccessNotification(trans('entities.pages_copy_success'));\n\n        return redirect($pageCopy->getUrl());\n    }\n\n    /**\n     * @throws PermissionsException\n     */\n    protected function ensureDraftAccess(Page $draft): void\n    {\n        if (!$draft->draft || $draft->created_by !== user()->id) {\n            throw new PermissionsException('This page is already published or does not belong to you.');\n        }\n    }\n}\n","sourceCodeStart":469,"sourceCodeEnd":491,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/app/Entities/Controllers/PageController.php#L469-L491","documentation":"PageController::ensureDraftAccess throws PermissionsException('This page is already published or does not belong to you.') when a draft page operation targets a page that either is no longer a draft ($draft->draft is false) or was created by a different user ($draft->created_by !== user()->id). Draft pages in BookStack are private to their creator until published, so other users (or actions on a since-published page) may not edit/delete them via draft endpoints.","triggerScenarios":"Calling editDraft/saveDraft/destroyDraft/store(revision) on a page that was already published (draft flag cleared); one user attempting to modify another user's draft by id; a stale client holding a draft id that has since been published; two users racing to edit the same draft.","commonSituations":"Scripts caching draft ids across long runs; collaborators expecting shared drafts (BookStack drafts are single-owner); a draft published in another tab while an edit form is still open.","solutions":["Check the page is still a draft before calling draft endpoints (page 'draft' flag true) and use the normal page-update endpoint once published","Only the draft creator should perform draft edits/deletes; if collaboration is needed, publish the page and use standard page permissions","Refresh the draft id from the API after publishing, since draft endpoints no longer apply","Handle the PermissionsException in clients and re-fetch the page to get its current state"],"exampleFix":"// before\n$pages->updateDraft($pageId, $data); // page may already be published\n// after\n$page = $pages->details($pageId);\nif ($page['draft']) { $pages->updateDraft($pageId, $data); }\nelse { $pages->update($pageId, $data); }","handlingStrategy":"type-guard","validationCode":"// Fetch the page first and verify it is still your draft\n$page = $api->get(\"/api/pages/{$id}\")->json();\nif ($page['draft'] === false || $page['created_by'] !== $myUserId) {\n    throw new RuntimeException('Page is published or owned by someone else; use normal page endpoints');\n}","typeGuard":"function isEditableDraft(array $page, int $myUserId): bool {\n    return !empty($page['draft']) && (int) $page['created_by'] === $myUserId;\n}","tryCatchPattern":"try {\n    $api->put(\"/api/pages/{$id}/draft\", $data);\n} catch (ClientException $e) {\n    if ($e->getResponse()->getStatusCode() === 403 || $e->getResponse()->getStatusCode() === 404) {\n        // re-fetch page: if published, switch to standard update endpoint\n    }\n    throw $e;\n}","preventionTips":["Re-fetch page state before each draft mutation instead of caching ids","Switch to standard page update endpoints as soon as the page is published","Remember drafts are single-owner; use published pages for collaboration","Handle stale-draft races in multi-tab or multi-user workflows"],"tags":["permissions","drafts","pages"],"backgroundTag":"draft-access-denied","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}