{"record":{"id":"e4e28e5ed95152e1","repo":"passbolt/passbolt_api","slug":"the-openpgp-armored-key-could-not-be-validated","errorCode":null,"errorMessage":"The OpenPGP armored key could not be validated.","messagePattern":"The OpenPGP armored key could not be validated\\.","errorType":"validation","errorClass":"App\\Error\\Exception\\ValidationException","httpStatus":400,"severity":"error","filePath":"src/Model/Table/GpgkeysTable.php","lineNumber":319,"sourceCode":"        if (!empty($info['expires'])) {\n            $data['expires'] = new DateTime($info['expires']);\n        }\n\n        $gpgKey = $this->newEntity($data, ['accessibleFields' => [\n            'user_id' => true,\n            'fingerprint' => true,\n            'bits' => true,\n            'type' => true,\n            'key_id' => true,\n            'uid' => true,\n            'armored_key' => true,\n            'key_created' => true,\n            'deleted' => true,\n            'expires' => true,\n        ]]);\n\n        if ($gpgKey->getErrors()) {\n            throw new ValidationException(__('The OpenPGP armored key could not be validated.'), $gpgKey, $this);\n        }\n\n        return $gpgKey;\n    }\n\n    /**\n     * Custom validation rule to validate key id\n     *\n     * @param string $value fingerprint\n     * @param array|null $context not in use\n     * @return bool\n     * @deprecated Use PublicKeyValidationService::isParsableArmoredPublicKey\n     */\n    public function isParsableArmoredPublicKey(string $value, ?array $context = null): bool\n    {\n        return PublicKeyValidationService::isParsableArmoredPublicKey($value);\n    }\n","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Model/Table/GpgkeysTable.php#L301-L337","documentation":"After building the Gpgkey entity, buildEntityFromArmoredKey() runs it through entity validation ($this->newEntity/build with rules). If the entity has errors (e.g. key not expired, valid email match, uid mismatch), it throws a ValidationException with this message carrying the entity errors.","triggerScenarios":"The armored key parses but fails field validation — key is expired, revoked, key_created in the future, uid/email does not match the user's email, or key type/algorithm not accepted.","commonSituations":"Users importing expired or revoked keys, keys generated with an email different from their account, or system clock skew making key_created appear in the future.","solutions":["Inspect the ValidationException errors property to see which rule failed (expires, uid, key_created, etc.).","Have the user generate/export a fresh non-expired key whose uid email matches their account.","Check server clock synchronization if key_created errors appear.","Fix client-side pre-validation to match the entity validation rules (expires, deleted flags)."],"exampleFix":"// before\n$gpgkey = $this->Gpgkeys->buildEntityFromArmoredKey($armoredKey, $userId); // ValidationException\n// after\ntry { $gpgkey = $this->Gpgkeys->buildEntityFromArmoredKey($armoredKey, $userId); }\ncatch (ValidationException $e) { $details = $e->getErrors(); // inspect which rule failed\n  throw new BadRequestException('GPG key rejected: ' . json_encode($details)); }","handlingStrategy":"try-catch","validationCode":"$info = PublicKeyValidationService::getPublicKeyInfo($armoredKey);\nif (isset($info['expires']) && $info['expires'] !== null && $info['expires'] < time()) {\n  throw new BadRequestException('The provided OpenPGP key is expired.');\n}\nif (!in_array($userEmail, array_column($info['uids'] ?? [], 'email'), true)) {\n  throw new BadRequestException('Key uid email must match the user email.');\n}","typeGuard":null,"tryCatchPattern":"try { $entity = $gpgkeysTable->buildEntityFromArmoredKey($armoredKey, $userId); }\ncatch (ValidationException $e) {\n  $errors = $e->getErrors(); // field-level detail (expires, uid, key_created...)\n  throw new BadRequestException(json_encode($errors));\n}","preventionTips":["Check key expiry and revocation before submission.","Ensure the key uid email equals the account email.","Keep the server clock NTP-synchronized to avoid key_created skew.","Surface the entity errors array to users instead of the generic message."],"tags":["openpgp","validation","gpg","entity-validation"],"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"}