passbolt/passbolt_api · error · App\Error\Exception\ValidationException

The OpenPGP armored key could not be validated.

Error message

The OpenPGP armored key could not be validated.

What it means

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.

Solutions

  1. Inspect the ValidationException errors property to see which rule failed (expires, uid, key_created, etc.).
  2. Have the user generate/export a fresh non-expired key whose uid email matches their account.
  3. Check server clock synchronization if key_created errors appear.
  4. Fix client-side pre-validation to match the entity validation rules (expires, deleted flags).

Example fix

// before
$gpgkey = $this->Gpgkeys->buildEntityFromArmoredKey($armoredKey, $userId); // ValidationException
// after
try { $gpgkey = $this->Gpgkeys->buildEntityFromArmoredKey($armoredKey, $userId); }
catch (ValidationException $e) { $details = $e->getErrors(); // inspect which rule failed
  throw new BadRequestException('GPG key rejected: ' . json_encode($details)); }
Defensive patterns

Strategy: try-catch

Validate before calling

$info = PublicKeyValidationService::getPublicKeyInfo($armoredKey);
if (isset($info['expires']) && $info['expires'] !== null && $info['expires'] < time()) {
  throw new BadRequestException('The provided OpenPGP key is expired.');
}
if (!in_array($userEmail, array_column($info['uids'] ?? [], 'email'), true)) {
  throw new BadRequestException('Key uid email must match the user email.');
}

Try / catch

try { $entity = $gpgkeysTable->buildEntityFromArmoredKey($armoredKey, $userId); }
catch (ValidationException $e) {
  $errors = $e->getErrors(); // field-level detail (expires, uid, key_created...)
  throw new BadRequestException(json_encode($errors));
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/e4e28e5ed95152e1. Report an issue: GitHub.

Appendix: source

Thrown at src/Model/Table/GpgkeysTable.php:319

        if (!empty($info['expires'])) {
            $data['expires'] = new DateTime($info['expires']);
        }

        $gpgKey = $this->newEntity($data, ['accessibleFields' => [
            'user_id' => true,
            'fingerprint' => true,
            'bits' => true,
            'type' => true,
            'key_id' => true,
            'uid' => true,
            'armored_key' => true,
            'key_created' => true,
            'deleted' => true,
            'expires' => true,
        ]]);

        if ($gpgKey->getErrors()) {
            throw new ValidationException(__('The OpenPGP armored key could not be validated.'), $gpgKey, $this);
        }

        return $gpgKey;
    }

    /**
     * Custom validation rule to validate key id
     *
     * @param string $value fingerprint
     * @param array|null $context not in use
     * @return bool
     * @deprecated Use PublicKeyValidationService::isParsableArmoredPublicKey
     */
    public function isParsableArmoredPublicKey(string $value, ?array $context = null): bool
    {
        return PublicKeyValidationService::isParsableArmoredPublicKey($value);
    }

View on GitHub (pinned to 31c1bbc10f)