{"record":{"id":"aca5df79a95b7f5d","repo":"passbolt/passbolt_api","slug":"the-openpgp-key-data-is-not-valid-setupcompleteservice","errorCode":null,"errorMessage":"The OpenPGP key data is not valid.","messagePattern":"The OpenPGP key data is not valid\\.","errorType":"validation","errorClass":"ValidationException","httpStatus":400,"severity":"error","filePath":"src/Service/Setup/SetupCompleteService.php","lineNumber":87,"sourceCode":"    {\n        // Check request sanity\n        $user = $this->getAndAssertUser($userId);\n        $token = $this->getAndAssertToken($userId, AuthenticationToken::TYPE_REGISTER);\n        $gpgkey = $this->getAndAssertGpgkey($userId);\n\n        // New with 3.6 - Check armored key content\n        // The key must not be expired or revoked, or have multiple key blocks, etc.\n        // TODO w4.0 - Move to getAndAssertGpgkey\n        //  Will break compat on recover for non compliant keys\n        PublicKeyValidationService::parseAndValidatePublicKey(\n            $gpgkey->armored_key,\n            PublicKeyValidationService::getStrictRules()\n        );\n\n        // Check business rules before saving\n        $this->Gpgkeys->checkRules($gpgkey);\n        if ($gpgkey->getErrors()) {\n            throw new ValidationException(__('The OpenPGP key data is not valid.'), $gpgkey, $this->Gpgkeys);\n        }\n\n        // Check key can be used to encrypt\n        // This can happen for example if the key is created in the future\n        // or some other issue prevent the backend to use it, we don't want to fail at the login step\n        if (Configure::read('passbolt.gpg.experimental.encryptValidate')) {\n            if (!PublicKeyCanEncryptCheckService::check($gpgkey->armored_key, $gpgkey->fingerprint)) {\n                $msg = __('The OpenPGP key can not be used to encrypt.');\n                Log::debug($msg, [$gpgkey->armored_key]);\n                throw new CustomValidationException($msg, ['gpgkey' => ['armored_key' => $msg]]);\n            }\n        }\n\n        // Consume atomically before the user save so a losing concurrent request never reaches persistence.\n        $this->consumeTokenOrFail($token);\n\n        $user->active = true;\n        $user->gpgkey = $gpgkey;","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Service/Setup/SetupCompleteService.php#L69-L105","documentation":"During setup/recover completion, the submitted OpenPGP public key passed syntax parsing but failed the Gpgkeys table business rules (checkRules), so a ValidationException is thrown carrying the entity errors. Passbolt throws this to prevent persisting a key that would break encryption for the account.","triggerScenarios":"POST to /setup/complete (or /recover/complete) with an armored key that violates model rules: invalid fingerprint checksum, mismatched key info versus armored key, duplicate fingerprint already registered, or missing/invalid key fields.","commonSituations":"User imports a different key than the one whose fingerprint is registered; key generated by non-compliant tooling; duplicate setup attempt with an already-stored key; truncated or edited armored key blocks.","solutions":["Regenerate the key with GnuPG (modern algo, not expired/revoked) and retry setup with the fresh armored key","Inspect the `errors` payload of the 400 response to see the exact failing Gpgkeys field","Ensure the armored key corresponds to the fingerprint recorded when the registration token was issued","Check the key has a single key block, valid user ID, and no future/invalid creation date"],"exampleFix":"// before: posting a mismatched key during setup\n{ \"gpgkey\": { \"armored_key\": \"-----BEGIN PGP PUBLIC KEY BLOCK----- ...other-identity-key...\" } }\n// after: use the key pair generated for this account\n{ \"gpgkey\": { \"armored_key\": \"-----BEGIN PGP PUBLIC KEY BLOCK----- ...account-key...\" } }","handlingStrategy":"validation","validationCode":"use App\\Service\\OpenPGP\\PublicKeyValidationService;\nPublicKeyValidationService::parseAndValidatePublicKey($armoredKey, PublicKeyValidationService::getStrictRules());","typeGuard":null,"tryCatchPattern":"try {\n    $user = $setupCompleteService->complete($userId);\n} catch (\\App\\Error\\Exception\\ValidationException $e) {\n    $fieldErrors = $e->getErrors(); // inspect gpgkey field errors\n}","preventionTips":["Generate keys with standard GnuPG defaults (modern algorithms)","Never edit or truncate armored key blocks","Ensure the submitted key matches the fingerprint registered with the invite","Test the key locally imports cleanly into gpg before submitting"],"tags":["openpgp","validation","setup"],"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-22T11:17:16.035Z"}