{"record":{"id":"ef61546229d343a3","repo":"passbolt/passbolt_api","slug":"account-recovery-is-mandatory-please-provide-the-mandatory","errorCode":null,"errorMessage":"Account recovery is mandatory. Please provide the mandatory data.","messagePattern":"Account recovery is mandatory\\. Please provide the mandatory data\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/AccountRecovery/src/Service/Setup/AccountRecoverySetupCompleteService.php","lineNumber":134,"sourceCode":"    }\n\n    /**\n     * Assert that there is not too much or not enough data\n     * Mandatory: both private key and password must be provided\n     * Disabled: none of them must be provided\n     *\n     * @return void\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if data is missing or too much data is sent\n     */\n    protected function assertRequestSanity(): void\n    {\n        if ($this->policy->isDisabled()) {\n            if ($this->isAccountRecoveryUserSettingProvided()) {\n                throw new BadRequestException(__('Account recovery is disabled. Key backup is not supported.'));\n            }\n        } elseif ($this->policy->isMandatory()) {\n            if (!$this->isPrivateKeyProvided() || !$this->arePasswordsProvided()) {\n                throw new BadRequestException(\n                    __('Account recovery is mandatory. Please provide the mandatory data.')\n                );\n            }\n        }\n    }\n\n    /**\n     * @return bool true if the account_recovery_user_setting data is set\n     */\n    protected function isAccountRecoveryUserSettingProvided(): bool\n    {\n        return is_array($this->request->getData('account_recovery_user_setting'));\n    }\n\n    /**\n     * @return bool true if the account_recovery_user_setting.account_recovery_private_key data is set\n     */\n    protected function isPrivateKeyProvided(): bool","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/AccountRecovery/src/Service/Setup/AccountRecoverySetupCompleteService.php#L116-L152","documentation":"Thrown in AccountRecoverySetupCompleteService::assertRequestSanity when the organization account recovery policy is 'mandatory' but the setup complete request omits required data: the account recovery private key or the server-stored passwords. A mandatory policy requires the user to hand over the private key and account passwords for escrow.","triggerScenarios":"POST /setup/setup/complete under a mandatory account recovery policy where the payload lacks account_recovery_private_key or the required password fields.","commonSituations":"Client (extension version mismatch or custom integration) not implementing the mandatory recovery fields; user bypassing the 'download mandatory data' step; policy changed to mandatory while an old client flow is mid-setup; API scripting/tests against a mandatory-policy instance without the fields.","solutions":["Ensure the setup complete payload includes the account_recovery_private_key and all required password fields","Update the browser extension / client to a version that supports mandatory account recovery","If the policy should not be mandatory, change the organization account recovery setting to 'opt-in' or 'disabled' in admin settings","Re-run the setup wizard from the start so the client collects the mandatory data"],"exampleFix":"// before\npayload = { authenticationtoken: token, user_setting: '...' };\n// after (mandatory policy)\npayload = { ...payload, account_recovery_private_key: armoredKey, account_recovery_password: pwd };","handlingStrategy":"validation","validationCode":"if (orgRecoveryPolicy === 'mandatory' &&\n    (!payload.account_recovery_private_key || !payload.account_recovery_password)) {\n  throw new Error('Mandatory recovery data missing');\n}","typeGuard":"const hasMandatoryRecoveryData = (p) => typeof p?.account_recovery_private_key === 'string' && p.account_recovery_private_key.length > 0 && typeof p?.account_recovery_password === 'string';","tryCatchPattern":"try {\n  await setupComplete(payload);\n} catch (e) {\n  if (e.code === 400 && /mandatory/.test(e.message)) {\n    await collectMandatoryRecoveryData();\n    await setupComplete(buildPayloadWithRecoveryData());\n  } else { throw e; }\n}","preventionTips":["Check the organization recovery policy early in the setup wizard and enforce required fields","Use an up-to-date browser extension that supports mandatory recovery","Do not bypass the 'provide key and passwords' step in scripted setups","Alert admins that switching to 'mandatory' requires all clients to comply"],"tags":["account-recovery","policy","missing-payload-field","http-400"],"backgroundTag":"missing-required-argument","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"}