passbolt/passbolt_api · error · InternalErrorException

Could not validate metadata key data.

Error message

Could not validate metadata key data.

What it means

setEncryptKeyWithMetadataKey() validates the metadata key entity via assertMetadataKey(); on failure it logs the key data (in debug) and throws an InternalErrorException with this message, chaining the original exception. It means the metadata key object is not usable for encryption (missing id, fingerprint, or armored key data).

Solutions

  1. Inspect the logged JSON of the metadata key (debug mode) to see which field failed validation
  2. Re-import the metadata key so fingerprint/armored_key are correctly populated (or fix the metadata_keys row)
  3. Ensure the code fetches complete key entities (no select() dropping fingerprint/armored_key) and skips deleted/expired keys
  4. Rerun the operation once the key passes assertMetadataKey

Example fix

// before: partially selected entity
$key = $this->MetadataKeys->find()->select(['id'])->firstOrFail();
$gpg = $this->setEncryptKeyWithMetadataKey($gpg, $key); // throws
// after: hydrate required fields and filter unusable keys
$key = $this->MetadataKeys->find()
    ->where(['deleted' => false, 'fingerprint IS NOT NULL'])
    ->firstOrFail();
$gpg = $this->setEncryptKeyWithMetadataKey($gpg, $key);
Defensive patterns

Strategy: validation

Validate before calling

$errors = (new \Passbolt\Metadata\Service\MetadataKeyAssertService())->assertMetadataKey($metadataKey);
// or manual check:
if (!$metadataKey->id || !$metadataKey->fingerprint || !$metadataKey->armoredKey) {
    throw new \LogicException('Metadata key data incomplete');
}

Type guard

function isValidMetadataKey(?\Passbolt\Metadata\Model\Entity\MetadataKey $k): bool {
    return $k !== null
        && $k->deleted === false
        && is_string($k->fingerprint) && strlen($k->fingerprint) === 40
        && is_string($k->armoredKey) && str_contains($k->armoredKey, 'PGP');
}

Try / catch

try {
    $gpg = $this->setEncryptKeyWithMetadataKey($gpg, $metadataKey);
} catch (\Cake\Http\Exception\InternalErrorException $e) {
    $root = $e->getPrevious();
    Log::error(json_encode($metadataKey->toArray()));
    // re-import the key into keyring, then retry
}

Prevention

When it happens

Trigger: Any metadata encryption flow (e.g. migrateShared, metadata key rotation, resource v5 creation) passing a metadata key that fails assertMetadataKey — e.g. key entity with empty fingerprint, deleted/expired key, or malformed armored_key.

Common situations: Metadata key marked expired/deleted but still selected; metadata_keys row with null fingerprint after an interrupted import; passing a partially hydrated entity fetched with select() omitting required columns; test fixtures with fake key data.

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/9fceb4df313791f9. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/Metadata/src/Service/OpenPGP/OpenPGPCommonMetadataOperationsTrait.php:47

    /**
     * Get the OpenPGP Backend ready to encryption with shared metadata key
     *
     * @param \App\Utility\OpenPGP\OpenPGPBackend $gpg for example OpenPGPBackendFactory::get()
     * @param \Passbolt\Metadata\Model\Entity\MetadataKey $metadataKey Metadata entity object.
     * @return \App\Utility\OpenPGP\OpenPGPBackend backend configured to use server keys
     * @throws \Cake\Http\Exception\InternalErrorException if the server key cannot be loaded
     */
    private function setEncryptKeyWithMetadataKey(OpenPGPBackend $gpg, MetadataKey $metadataKey): OpenPGPBackend
    {
        // Set encryption key as the metadata key
        try {
            $this->assertMetadataKey($metadataKey);
        } catch (Exception $exception) {
            if (Configure::read('debug')) {
                Log::error(json_encode($metadataKey));
            }
            $msg = __('Could not validate metadata key data.');
            throw new InternalErrorException($msg, 500, $exception);
        }
        try {
            $gpg->setEncryptKeyFromFingerprint($metadataKey->fingerprint);
        } catch (Exception $exception) {
            // Try to import the key in keyring again
            try {
                $gpg->importKeyIntoKeyring($metadataKey->armored_key);
                $gpg->setEncryptKeyFromFingerprint($metadataKey->fingerprint);
            } catch (Exception $exception) {
                if (Configure::read('debug')) {
                    Log::error(json_encode($metadataKey));
                }
                $msg = __('Could not import the metadata OpenPGP key.');
                throw new InternalErrorException($msg, 500, $exception);
            }
        }

        return $gpg;

View on GitHub (pinned to 31c1bbc10f)