{"record":{"id":"78f876d7ac4745ce","repo":"passbolt/passbolt_api","slug":"exception-getmessage-dynamic-from-wrapped","errorCode":null,"errorMessage":"$exception->getMessage() (dynamic, from wrapped ValidationException)","messagePattern":"\\$exception->getMessage\\(\\) \\(dynamic, from wrapped ValidationException\\)","errorType":"validation","errorClass":"CustomValidationException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryUserSettings/AccountRecoveryUserSettingsSetService.php","lineNumber":150,"sourceCode":"     */\n    protected function validateStatusAgainstOrganizationPolicy(AccountRecoveryUserSetting $setting): void\n    {\n        if ($this->organizationPolicy->isMandatory() && $setting->isRejected()) {\n            throw new BadRequestException(__('The account recovery is mandatory and cannot be rejected.'));\n        }\n    }\n\n    /**\n     * @param string $status Status\n     * @throws \\App\\Error\\Exception\\CustomValidationException if the settings does not validate\n     * @return \\Passbolt\\AccountRecovery\\Model\\Entity\\AccountRecoveryUserSetting\n     */\n    protected function validateAccountRecoveryUserSetting(string $status): AccountRecoveryUserSetting\n    {\n        try {\n            return $this->AccountRecoveryUserSettings->buildAndValidateEntity($this->uac, $status);\n        } catch (ValidationException $exception) {\n            throw new CustomValidationException($exception->getMessage(), [\n                'account_recovery_user_setting' => $exception->getErrors(),\n            ]);\n        }\n    }\n\n    /**\n     * Check that the user selected setting makes sense as per select org policy\n     *\n     * @param \\Passbolt\\AccountRecovery\\Model\\Entity\\AccountRecoveryUserSetting $setting entity\n     * @throws \\Cake\\Http\\Exception\\BadRequestException if user rejects and policy is mandatory\n     * @return void\n     */\n    protected function assertRules(AccountRecoveryUserSetting $setting): void\n    {\n        if ($this->organizationPolicy->isMandatory() && !$setting->isApproved()) {\n            throw new CustomValidationException(__('Invalid request. You cannot opt-out.'), [\n                'account_recovery_user_setting' => [\n                    'status' => [","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryUserSettings/AccountRecoveryUserSettingsSetService.php#L132-L168","documentation":"validateAccountRecoveryUserSetting() wraps CakePHP ValidationException raised by buildAndValidateEntity() into a CustomValidationException, propagating the original message plus errors under the 'account_recovery_user_setting' key. The message is dynamic and comes from the underlying table validation rules.","triggerScenarios":"Submitting a status value that fails entity validation (invalid status enum, missing user, rule violation) via the account recovery user settings endpoint.","commonSituations":"Typos in the status field ('approve' vs 'approved'); payloads missing required fields; schema changes adding new validation rules not handled by older clients.","solutions":["Inspect the errors object in the response (account_recovery_user_setting.*) for the failing rule","Send one of the allowed status values and include all required fields","Update the client to the latest API schema for account recovery settings"],"exampleFix":"// before\n$service->set(['status' => 'approve']);\n// after\n$service->set(['status' => 'approved']);","handlingStrategy":"validation","validationCode":"const VALID = ['approved','rejected']; if (!VALID.includes(data.status)) throw new Error('invalid status');","typeGuard":"const isStatus = (v) => ['approved','rejected'].includes(v);","tryCatchPattern":"try { await setSettings(data); } catch (e) { if (e.body?.account_recovery_user_setting) { showFieldErrors(e.body.account_recovery_user_setting); } }","preventionTips":["Validate status against the allowed enum client-side","Keep client schemas in sync with the API version","Surface the nested errors object to users"],"tags":["validation","account-recovery","bad-request"],"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"}