{"record":{"id":"db3100c7e4f2b524","repo":"passbolt/passbolt_api","slug":"invalid-request-private-key-or-password-are-missing","errorCode":null,"errorMessage":"Invalid request. Private key or password are missing.","messagePattern":"Invalid request\\. Private key or password are missing\\.","errorType":"validation","errorClass":"CustomValidationException","httpStatus":400,"severity":"error","filePath":"plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryUserSettings/AccountRecoveryUserSettingsSetService.php","lineNumber":197,"sourceCode":"                        'isMatchingData' => __('The status must be set to approved.'),\n                    ],\n                ],\n            ]);\n        }\n\n        if ($setting->isApproved() && (!$this->isPrivateKeyProvided() || !$this->arePasswordsProvided())) {\n            $e = [];\n            if (!$this->isPrivateKeyProvided()) {\n                $e['account_recovery_user_setting']['account_recovery_private_key'] = [\n                    '_required' => __('The private key backup must be provided.'),\n                ];\n            }\n            if (!$this->arePasswordsProvided()) {\n                $e['account_recovery_user_setting']['account_recovery_private_key_passwords'] = [\n                    '_required' => __('The private key backup must be provided.'),\n                ];\n            }\n            throw new CustomValidationException(__('Invalid request. Private key or password are missing.'), $e);\n        }\n    }\n\n    /**\n     * @throws \\App\\Error\\Exception\\CustomValidationException if the private key does not validate\n     * @return \\Passbolt\\AccountRecovery\\Model\\Entity\\AccountRecoveryPrivateKey\n     */\n    protected function validateAccountRecoveryPrivateKey(): AccountRecoveryPrivateKey\n    {\n        $data = $this->data['account_recovery_private_key'] ?? [];\n        try {\n            // Entity validation &\n            $privateKeyEntity = $this->AccountRecoveryPrivateKeys->buildAndValidateEntity($this->uac, $data);\n\n            // Validate private key OpenPGP message &\n            $rules = MessageValidationService::getSymmetricMessageRules();\n            MessageValidationService::parseAndValidateMessage($privateKeyEntity->data, $rules);\n","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/AccountRecovery/src/Service/AccountRecoveryUserSettings/AccountRecoveryUserSettingsSetService.php#L179-L215","documentation":"assertRules() throws this when the setting is approved (enrolling) but the required backup material is absent: no private key and/or no private key passwords provided. The structured errors mark the missing fields (_required).","triggerScenarios":"POST/PATCH with status=approved but an empty account_recovery_private_key, or missing account_recovery_private_key_passwords, in the payload; truncated form submissions.","commonSituations":"Client-side generation of the backup key failed silently; field names mismatched after an API version change; users submitting before the key export step completes.","solutions":["Include both account_recovery_private_key and account_recovery_private_key_passwords when enrolling","Verify the client completed key generation/encryption before submitting","Check the response errors object to see which field is missing","Upgrade the client if it targets an older payload schema"],"exampleFix":"// before\n$service->set(['status' => 'approved']);\n// after\n$service->set(['status' => 'approved',\n    'account_recovery_private_key' => $armoredKey,\n    'account_recovery_private_key_passwords' => $passwords]);","handlingStrategy":"validation","validationCode":"if (status === 'approved' && (!privateKey || !passwords?.length)) throw new Error('approved status requires private key and passwords');","typeGuard":"const hasBackup = (d) => Boolean(d.account_recovery_private_key) && Array.isArray(d.account_recovery_private_key_passwords) && d.account_recovery_private_key_passwords.length > 0;","tryCatchPattern":"try { await setSettings(data); } catch (e) { if (e.body?.account_recovery_user_setting?.account_recovery_private_key_passwords?._required) { /* prompt for backup */ } }","preventionTips":["Complete key generation/encryption before enabling submit","Validate required fields client-side for approved status","Log payload shape in dev to catch schema drift"],"tags":["validation","missing-field","account-recovery"],"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"}