{"record":{"id":"bd830a3ef62d39ff","repo":"passbolt/passbolt_api","slug":"could-not-validate-the-transfer-data-transfersupdateservice","errorCode":null,"errorMessage":"Could not validate the transfer data.","messagePattern":"Could not validate the transfer data\\.","errorType":"validation","errorClass":"ValidationException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltCe/Mobile/src/Service/Transfers/TransfersUpdateService.php","lineNumber":87,"sourceCode":"     * @param \\Passbolt\\Mobile\\Model\\Entity\\Transfer $transfer entity\n     * @param array $data entity data\n     * @param \\App\\Utility\\UserAccessControl $uac user access control object\n     * @throws \\App\\Error\\Exception\\ValidationException if data do not validate\n     * @throws \\Cake\\Http\\Exception\\InternalErrorException if saving data is not possible\n     * @return \\Passbolt\\Mobile\\Model\\Entity\\Transfer\n     */\n    public function update(Transfer $transfer, array $data, UserAccessControl $uac): Transfer\n    {\n        $this->assertOperationIsAllowed($transfer, $uac);\n\n        // Check for validation errors\n        $originalTransfer = clone $transfer;\n        $transfer = $this->patchTransferEntity($transfer, $data);\n        $this->assertTransitionAllowed($originalTransfer, $transfer);\n\n        if ($transfer->getErrors()) {\n            $msg = __('Could not validate the transfer data.');\n            throw new ValidationException($msg, $transfer, $this->Transfers);\n        }\n\n        // Save and check for application rules errors.\n        $transferSaved = $this->Transfers->save($transfer);\n        if ($transfer->getErrors()) {\n            $msg = __('Could not update the transfer data.');\n            throw new ValidationException($msg, $transfer, $this->Transfers);\n        }\n\n        // Check for errors while saving.\n        if (!$transferSaved) {\n            throw new InternalErrorException(__('The transfer could not be updated.'));\n        }\n\n        return $transfer;\n    }\n\n    /**","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/Mobile/src/Service/Transfers/TransfersUpdateService.php#L69-L105","documentation":"A ValidationException thrown by TransfersUpdateService::update when the patched Transfer entity fails field validation BEFORE any save is attempted, and additionally after assertTransitionAllowed() checks the status transition. It carries the entity and table so per-field errors are available to callers.","triggerScenarios":"PATCH/PUT /mobile/transfers/<id> with payload fields that fail validation — e.g. non-numeric current_page, negative page numbers, invalid status string, or a patch that leaves the entity in an inconsistent state (current_page > total_pages).","commonSituations":"Client sending pages as strings or 1-based indexes when the API expects 0-based; sending an off-by-one current_page greater than or equal to total_pages; status typos like 'completed' instead of 'complete'; stale client state after another device cancelled the transfer.","solutions":["Inspect the exception's entity errors for the exact failing field","Send current_page as a 0-based integer strictly less than total_pages","Use exact status values: start, in_progress, complete, cancel","Refetch the transfer state before patching to avoid patching a transfer modified elsewhere","Do not patch fields that are not part of the update whitelist"],"exampleFix":"// before\npatch(['current_page' => '3', 'status' => 'completed']); // string page, wrong status\n// after\npatch(['current_page' => 2, 'status' => 'complete']); // 0-based int < total_pages","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(p.current_page) || p.current_page < 0 || p.current_page >= p.total_pages) throw new Error('current_page must be a 0-based int < total_pages');\nif (!['in_progress','complete','cancel'].includes(p.status)) throw new Error('invalid update status');","typeGuard":null,"tryCatchPattern":"try { return await patchTransfer(id, payload); } catch (e) { if (e.status === 400 && e.body?.errors) { syncFromServerAndReapply(); } throw e; }","preventionTips":["Validate page math client-side before every patch","Use exact enum strings for status","Refetch transfer state before updating to avoid stale patches","Only send whitelisted fields in update payloads"],"tags":["validation","mobile","transfers","cakephp","update"],"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"}