passbolt/passbolt_api · error · CustomValidationException
Could not validate message data.
Error message
Could not validate message data.
What it means
MessageRecipientValidationService::isMessageForRecipient validates that an OpenPGP armored message is encrypted for the expected recipient key. If $messageInfo has no recipients (recipients[0] missing), the message cannot be attributed to any key, so it throws CustomValidationException with 'Could not validate message data.' and a recipientRequired error.
Solutions
- Re-generate the armored message so GnuPG/OpenPGP-PHP can parse recipient key IDs (use modern subkeys/ciphers).
- Verify the message parses: gpg --list-packets on the armored block to confirm recipient packets exist.
- Ensure the shared secret payload is the complete encrypted message, not a fragment.
- Check the OpenPGP backend version supports the cipher/key format used.
Example fix
// before
$service->isMessageForRecipient($messageInfo, $keyInfo); // throws: no recipients
// after
if (!empty($messageInfo['recipients'])) {
$service->isMessageForRecipient($messageInfo, $keyInfo);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (!Array.isArray(messageInfo.recipients) || messageInfo.recipients.length === 0) { /* reject before call */ } Type guard
function hasRecipients(m) { return Array.isArray(m?.recipients) && m.recipients.length > 0; } Try / catch
try { isMessageForRecipient($mi, $ki); } catch (CustomValidationException $e) { /* recipientRequired error */ } Prevention
- Verify messages with gpg --list-packets before sharing
- Re-encrypt with supported GPG versions
- Never transmit truncated armored payloads
When it happens
Trigger: Decrypting/sharing operations (buildPasswordEntitiesFromDataOrFail, folder/resource assertions) receiving an armored message whose parsed metadata contains an empty recipients array — e.g. message encrypted with unsupported/legacy ciphers or corrupted packet headers.
Common situations: Messages produced by non-passbolt GPG tools, corrupted or truncated armored payloads, key info mismatch (PB-43936: keys without subkeys), sharing endpoints receiving malformed secrets.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- A valid OpenPGP key must be provided.
- Could not validate user data.
- Invalid request, message validation rules are missing.
- The armored message could not be validated.
- The OpenPGP armored key could not be validated.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/9752cfab06111346.
Report an issue: GitHub.
Appendix: source
Thrown at src/Service/OpenPGP/MessageRecipientValidationService.php:35
namespace App\Service\OpenPGP;
use App\Error\Exception\CustomValidationException;
/**
* Service to check if an OpenPGP message is intended for a recipient
*/
class MessageRecipientValidationService
{
/**
* @param array $messageInfo see MessageValidationService::getMessageInfo
* @param array $keyInfo see PublicKeyValidationService::getPublicKeyInfo
* @throws \App\Error\Exception\CustomValidationException if the message info or key info are not workable
* @return bool
*/
public static function isMessageForRecipient(array $messageInfo, array $keyInfo): bool
{
if (!isset($messageInfo['recipients'][0])) {
throw new CustomValidationException(__('Could not validate message data.'), [
'recipientRequired' => __('Recipient information could not be found.'),
]);
}
// PB-43936 OpenPGP key without subkey, then the message must for main key id.
if (empty($keyInfo['sub_keys'])) {
return isset($keyInfo['key_id']) && in_array($keyInfo['key_id'], $messageInfo['recipients']);
}
foreach ($keyInfo['sub_keys'] as $subKey) {
if (isset($subKey['key_id']) && in_array($subKey['key_id'], $messageInfo['recipients'])) {
return true;
}
}
return false;
}
}View on GitHub (pinned to 31c1bbc10f)