passbolt/passbolt_api · error · InternalErrorException
The metadata could not be encrypted with the metadata key…
Error message
{exceptionMessage} The metadata could not be encrypted with the metadata key id: {0}. What it means
Shared-folder migration encrypts metadata with the active metadata (shared) key; any exception from backend setup, metadata key loading, JSON encoding, or gpg->encrypt() is re-thrown as InternalErrorException prefixed with the original message and suffixed with the metadata key ID, chaining the original exception.
Solutions
- Inspect the prefixed exceptionMessage / chained exception to find the root GPG error.
- Verify the metadata key is active, not expired/revoked, and its armored public key imports cleanly into the keyring.
- Check GNUPGHOME configuration and permissions for the PHP process, and that setEncryptKeyWithMetadataKey succeeded.
- Validate the metadata payload is UTF-8 clean before json_encode, or sanitize folder names first.
Example fix
// before
$metadataClearText = json_encode($metadataArray, JSON_THROW_ON_ERROR);
$metadataEncrypted = $gpg->encrypt($metadataClearText, true);
// after: guard encoding and key import
$metadataClearText = json_encode(
$this->sanitizeUtf8($metadataArray),
JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE
);
if (!$metadataKey->expired && !$metadataKey->deleted) {
$metadataEncrypted = $gpg->encrypt($metadataClearText, true);
} Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: metadata key active and importable
$gpg = OpenPGPBackendFactory::get();
$gpg->clearKeys();
$gpg->importKeyIntoKeyring($metadataKey->armored_key);
$gpg->encrypt('test', true); // smoke-test encryption with the metadata key Try / catch
try {
$service->migrate($uac);
} catch (\Cake\Http\Exception\InternalErrorException $e) {
error_log($e->getPrevious()?->getMessage() ?? $e->getMessage());
// re-import/rotate the metadata key identified in the message, then retry
} Prevention
- Smoke-test encryption with the active metadata key before batch migration
- Rotate metadata keys before expiry and keep the keyring in sync with the DB
- Ensure folder names are valid UTF-8 to avoid json_encode (JSON_THROW_ON_ERROR) failures
- Confirm GNUPGHOME configuration for the process running the migration
When it happens
Trigger: Calling migrate → migrateShared when encryption with the metadata key fails: key material/fingerprint invalid or missing from keyring, key expired/revoked, gpg binary issues, or JSON_THROW_ON_ERROR firing while encoding the metadata array.
Common situations: Metadata key deleted from keyring but row still active; mismatched armored key data in DB; wrong GNUPGHOME; folder names with invalid UTF-8 breaking json_encode.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- The metadata could not be encrypted with the metadata key id
- 500
- Could not validate metadata key data.
- The metadata could not be encrypted with the user id: .
- The metadata could not be encrypted with the user id: .
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/b5925d6d0c79f829.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/Metadata/src/Service/Migration/MigrateAllV4FoldersToV5Service.php:203
* @return void
* @throws \Cake\Datasource\Exception\RecordNotFoundException When there is no metadata key record.
*/
private function migrateShared(MetadataFolderDto $dto, Folder $folder): void
{
$metadataArray = $dto->getClearTextMetadata();
$metadataKey = $this->getMetadataKeyForEncryption();
try {
$gpg = OpenPGPBackendFactory::get();
$gpg->clearKeys();
$gpg = $this->setSignKeyWithServerKey($gpg);
$gpg = $this->setEncryptKeyWithMetadataKey($gpg, $metadataKey);
$metadataClearText = json_encode($metadataArray, JSON_THROW_ON_ERROR);
$metadataEncrypted = $gpg->encrypt($metadataClearText, true);
} catch (Exception $exception) {
$msg = $exception->getMessage() . ' ';
$msg .= __('The metadata could not be encrypted with the metadata key id: {0}.', $metadataKey->id);
throw new InternalErrorException($msg, 500, $exception);
}
$this->updateFolder($folder, [
'name' => null,
'metadata' => $metadataEncrypted,
'metadata_key_id' => $metadataKey->id,
'metadata_key_type' => 'shared_key',
//TODO support nullable resource.modified_by to allow server side modification
//'modified_by' => null,
]);
}
/**
* Updates entity with given data.
*
* @param \Passbolt\Folders\Model\Entity\Folder $folder Folder entity to update.
* @param array $data Data to update.
* @return voidView on GitHub (pinned to 31c1bbc10f)