{"record":{"id":"8a31aa5882dd6882","repo":"passbolt/passbolt_api","slug":"could-not-validate-move-data-8a31aa","errorCode":null,"errorMessage":"Could not validate move data.","messagePattern":"Could not validate move data\\.","errorType":"validation","errorClass":"App\\Error\\Exception\\CustomValidationException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/Folders/src/Service/FoldersRelations/FoldersRelationsMoveItemInUserTreeService.php","lineNumber":140,"sourceCode":"        $exists = $this->foldersRelationsTable->isItemInUserTree($uac->getId(), $folderParentId);\n        if (!$exists) {\n            $errors = ['folder_parent_id' => ['folder_exists' => 'The folder parent does not exist.']];\n            $this->handleValidationErrors($errors);\n        }\n    }\n\n    /**\n     * Handle move validation errors.\n     *\n     * @param array|null $errors The list of errors\n     * @return void\n     * @throws \\App\\Error\\Exception\\CustomValidationException If the provided data does not validate.\n     */\n    private function handleValidationErrors(?array $errors = []): void\n    {\n        if (!empty($errors)) {\n            $msg = __('Could not validate move data.');\n            throw new CustomValidationException($msg, $errors, $this->foldersRelationsTable);\n        }\n    }\n\n    /**\n     * Check if the user can move content out of the folder.\n     * - User can always move content from root.\n     * - User can always move content out of a personal folder.\n     * - User can move content out of a shared folder if the user has at least an update permission on the folder to\n     *   move and the original parent folder.\n     *\n     * @param \\App\\Utility\\UserAccessControl $uac The user at the origin of the operation\n     * @param string $foreignModel The entity model\n     * @param string $foreignId The entity id\n     * @param string|null $originalFolderParentId The original folder location. Null if root\n     * @return void\n     */\n    private function assertUserCanMoveOutOfFolder(\n        UserAccessControl $uac,","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/Folders/src/Service/FoldersRelations/FoldersRelationsMoveItemInUserTreeService.php#L122-L158","documentation":"This CustomValidationException is thrown when the move-operation data fails validation. FoldersRelationsMoveItemInUserTreeService aggregates errors from its assertion methods (folder parent validity, permission to move out of / into a folder, cycle detection) and, if any errors accumulated, handleValidationErrors raises this exception carrying the per-field error array. It protects the personal-folder-tree invariants before any persistence happens.","triggerScenarios":"Calling the folders move endpoint (PUT /folders/<id>/move or resource move) where: the folder_parent_id points to a non-existent or invalid folder; the user lacks permission on the source folder to move content out; the user lacks permission on the destination folder to move content in; or the move would create a cycle in the folder hierarchy (moving a folder into one of its own descendants).","commonSituations":"Front-end passes a stale folder_parent_id after a folder was deleted by another user; a user with read-only access on a parent folder tries to move items; automation/scripts try to move a folder into its own subtree; passing an id belonging to a resource where a folder id is expected (or vice versa).","solutions":["Inspect the 'errors' payload of the exception response — it tells which assertion failed (folder_parent_id, permission, or cycle).","Verify the folder_parent_id exists and is a folder id, not a resource id, and was not deleted (check GET /folders).","Confirm the authenticated user has the required permission (UPDATE/OWNER) on both the source and destination folders.","Ensure the move does not place a folder inside its own descendant tree; re-parent the destination folder first if needed.","Fix client validation to check cycle and permission rules before issuing the move request."],"exampleFix":"// before: move without checks\nawait moveFolder(folderId, { folder_parent_id: parentId });\n\n// after: validate first\nif (await isDescendant(parentId, folderId)) {\n  throw new Error('Cannot move a folder into its own descendant');\n}\nawait moveFolder(folderId, { folder_parent_id: parentId });","handlingStrategy":"validation","validationCode":"const parentExists = folders.some(f => f.id === moveData.folder_parent_id);\nconst createsCycle = await isDescendant(moveData.folder_parent_id, folderId);\nif (!parentExists || createsCycle) throw new Error('Invalid move: bad parent or cycle');","typeGuard":null,"tryCatchPattern":"try { await moveFolder(id, data); } catch (e) { if (e.response?.status === 400 && e.response?.data?.errors) handleFieldErrors(e.response.data.errors); else throw e; }","preventionTips":["Always validate folder_parent_id against the current folder list before moving.","Implement client-side cycle detection before issuing move calls.","Check user permissions on both source and destination folders in the UI.","Surface the per-field errors payload from the API to the user instead of failing silently."],"tags":["folders","validation","permissions","move-operation"],"backgroundTag":"schema-validation-failed","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}