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
- Inspect the logged JSON of the metadata key (debug mode) to see which field failed validation
- Re-import the metadata key so fingerprint/armored_key are correctly populated (or fix the metadata_keys row)
- Ensure the code fetches complete key entities (no select() dropping fingerprint/armored_key) and skips deleted/expired keys
- 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
- Enable debug mode when operating metadata migrations so the failing key data is logged
- Always fetch metadata key entities with all columns (avoid select() dropping fingerprint/armored_key)
- Filter out deleted/expired keys before selecting a key for encryption
- Validate key data (assertMetadataKey) at ingestion time, not only at encryption time
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
- The metadata could not be encrypted with the metadata key…
- The metadata could not be encrypted with the metadata key id
- The OpenPGP key can not be used to encrypt.
- 500
- A valid OpenPGP key must be provided.
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)