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

  1. Re-generate the armored message so GnuPG/OpenPGP-PHP can parse recipient key IDs (use modern subkeys/ciphers).
  2. Verify the message parses: gpg --list-packets on the armored block to confirm recipient packets exist.
  3. Ensure the shared secret payload is the complete encrypted message, not a fragment.
  4. 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

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


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)