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
Personal tag metadata is encrypted with the owning user's OpenPGP public key. If the user entity has no gpgkey loaded or the user genuinely has no key, the service throws InternalErrorException combining 'No OpenPGP key found for the user.' with the user id context.
Solutions
- Add the Gpgkeys containment to the migration query: contain(['Users' => ['Gpgkeys']]).
- Have the affected user complete OpenPGP key setup, then rerun migration.
- Delete or reassign the tag if the owner is a provisioned account that will never have a key.
- Pre-check users without keys and exclude their tags from the batch.
Example fix
// before $tags = $this->Tags->find()->contain(['Users'])->all(); // after $tags = $this->Tags->find()->contain(['Users' => ['Gpgkeys']])->all();
Defensive patterns
Strategy: validation
Validate before calling
$keyless = $usersTable->find()
->leftJoinWith('Gpgkeys')
->where(['Gpgkeys.id IS NULL'])
->all();
// exclude tags owned by $keyless users from the migration batch Type guard
function hasGpgKey(User $user): bool {
return $user->gpgkey !== null && $user->gpgkey->fingerprint !== null;
} Try / catch
try {
$service->migrate($uac, $batch);
} catch (InternalErrorException $e) {
if (str_contains($e->getMessage(), 'No OpenPGP key found')) {
$this->log('Owner lacks GPG key; defer tag migration');
} else { throw $e; }
} Prevention
- Contain Gpgkeys: contain(['Users' => ['Gpgkeys']])
- Require key setup before users create personal tags
- Report users without keys before scheduling migration
- Reassign tags from key-less provisioned accounts
When it happens
Trigger: Migrating a personal tag whose owner has no OpenPGP key registered (user never completed key setup) or where the migration query did not contain the user's gpgkey association.
Common situations: Legacy users created via LDAP/SCIM provisioning without completing passbolt key setup; migration batch query missing contain(['Users' => ['Gpgkeys']]); suspended/deleted accounts owning active tags.
Related errors
- 500
- No user found for the personal tag id
- Tag creation with cleartext metadata not allowed.
- Tag ID " " is already V5
- The tag metadata key data could not be updated.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/78d1a2aed8d9ef1e.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Tags/src/Service/Metadata/MigrateAllV4TagsToV5Service.php:211
*/
private function migratePersonal(MetadataTagDto $dto, Tag $tag): void
{
$metadataArray = $dto->getClearTextMetadata();
$users = $tag->get('users');
if (!is_array($users) || count($users) < 1) {
throw new InternalErrorException(__('No user found for the personal tag id: "{0}".', $tag->id));
}
/** @var \App\Model\Entity\User $user */
$user = $users[0];
if (is_null($user)) {
throw new InternalErrorException(__('User contain data missing for the tag id: "{0}".', $tag->id));
}
if (is_null($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->updateTag($tag, [
'slug' => null,
'metadata' => $metadataEncrypted,View on GitHub (pinned to 31c1bbc10f)