passbolt/passbolt_api · error · InternalErrorException
No OpenPGP key found for the user. The metadata could not…
Error message
No OpenPGP key found for the user. The metadata could not be encrypted with the user id: {0}. What it means
Thrown in migratePersonal() when the permission's user exists but has no associated OpenPGP key (user->gpgkey is null). Personal-resource V5 metadata must be encrypted with that user's public key, so migration cannot proceed. The resource is skipped and the error is recorded in the migration result errors array.
Solutions
- Have the user complete account setup so an OpenPGP key is generated, then re-run migration.
- Reassign the resource ownership to a user who has a valid OpenPGP key, then re-run migration.
- Import/restore the user's missing gpgkeys row if the key exists elsewhere.
- Pre-screen users with V4 personal resources for missing gpgkeys and fix accounts before running the migration.
Example fix
// before: user exists but gpgkeys table has no row for user_id // after: reassign ownership to a user with a key UPDATE permissions SET aro_foreign_key = '<user-with-gpgkey-id>' WHERE id = '<permission-id>';
Defensive patterns
Strategy: validation
Validate before calling
// before migrating, find active users without an OpenPGP key who own V4 resources
$missingKeys = $usersTable->find()
->leftJoinWith('Gpgkeys')
->innerJoinWith('Permissions', fn ($q) => $q->where(['Permissions.aro' => 'User']))
->where(['Gpgkeys.id IS' => null])
->all(); Type guard
$gpgkey = $user->gpgkey ?? null;
if (!$gpgkey instanceof \App\Model\Entity\Gpgkey) { skip($resource); } Prevention
- Require users to complete setup (key generated) before granting resource ownership.
- Audit users-without-keys that own V4 resources before migration.
- Back up gpgkeys table alongside users when restoring.
- Reassign personal resources to keyed users when accounts are stuck in setup.
When it happens
Trigger: migrate() -> migratePersonal() on a resource with exactly one non-group permission whose user record exists but has no row in gpgkeys (user never completed setup, key was hard-deleted, or the Gpgkeys contain failed to match).
Common situations: Admin-created user accounts that never finished the OpenPGP setup flow owning personal resources; database restores that lost gpgkeys rows; users whose keys were removed during account fixes.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- The metadata could not be encrypted with the user id: .
- Can not encrypt without a key. Set a public key first.
- The metadata could not be encrypted with the user id: .
- The metadata could not be encrypted with the metadata key…
- No OpenPGP key found for the user. The metadata could not…
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/725297d6b12e793c.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/Metadata/src/Service/Migration/MigrateAllV4ResourcesToV5Service.php:167
* @throws \Cake\Http\Exception\InternalErrorException When resource type mapping is does not exist.
*/
private function migratePersonal(MetadataResourceDto $dto, Resource $resource): void
{
$metadataArray = $dto->getClearTextMetadata();
/** @var \App\Model\Entity\Permission $permission */
$permission = $resource->get('permissions')[0];
$user = $permission->user;
if (!isset($user)) {
$msg = __('No user provided.') . ' ';
$msg .= __('The metadata could not be encrypted for permission id: {0}.', $permission->id);
throw new InternalErrorException($msg);
}
if (!isset($user->gpgkey)) {
$msg = __('No OpenPGP key found for the user.') . ' ';
$msg .= __('The metadata could not be encrypted with the user id: {0}.', $user->id);
throw new InternalErrorException($msg);
}
try {
$gpg = OpenPGPBackendFactory::get();
$gpg->clearKeys();
$gpg = $this->setSignKeyWithServerKey($gpg);
$gpg = $this->setEncryptKeyWithUserKey($gpg, $user->gpgkey);
$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 user id: {0}.', $user->id);
throw new InternalErrorException($msg, 500, $exception);
}
$this->updateResource($resource, [
'name' => null,
'username' => null,
'uri' => null,View on GitHub (pinned to 31c1bbc10f)