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
Continuation of migratePersonal's guards: the permission's user exists but has no GPG key (user->gpgkey is null), so the clear-text folder metadata cannot be encrypted. An InternalErrorException combining 'No OpenPGP key found for the user.' with the user ID is thrown.
Solutions
- Have the affected user upload an OpenPGP key (or restore their key) before running the migration.
- Exclude users without keys from migration targets and handle them separately.
- Ensure the query contains Gpgkeys under Permissions.Users so existing keys are hydrated.
- Pre-check with SQL: active users with folder permissions but no gpgkeys row.
Example fix
// before
$folders = $foldersTable->find()->contain(['Permissions.Users'])->all();
// after
$folders = $foldersTable->find()
->contain(['Permissions.Users.Gpgkeys'])
->innerJoinWith('Permissions.Users.Gpgkeys')
->all(); Defensive patterns
Strategy: type-guard
Validate before calling
$usersWithoutKeys = TableRegistry::getTableLocator()->get('Users')
->find('activeNotDeleted')
->innerJoinWith('Gpgkeys', function ($q) { return $q; })
->notMatching('Gpgkeys')->all(); // or simply: users with folder permissions but no key Type guard
if ($user === null || $user->gpgkey === null) {
continue; // cannot encrypt for this user
} Try / catch
try {
$service->migrate($uac);
} catch (\Cake\Http\Exception\InternalErrorException $e) {
if (str_contains($e->getMessage(), 'No OpenPGP key found for the user.')) {
// have that user (id in message) upload a key, then retry
}
} Prevention
- Contain Gpgkeys in the migration query so existing keys are loaded
- Block folder migrations for users lacking OpenPGP keys, or generate/restore keys first
- Run the passbolt healthcheck for missing user keys periodically
When it happens
Trigger: Migrating a personal folder owned by an active user who never uploaded an OpenPGP key, or whose gpgkeys row was deleted / contain('Gpgkeys') omitted from the query.
Common situations: Never-activated-but-active users without completed setup; key deletions during user cleanup; missing Gpgkeys contain() in the migration fetch.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- The metadata could not be encrypted with the user id: .
- The metadata could not be encrypted with the metadata key…
- The metadata could not be encrypted with the user id: .
- No OpenPGP key found for the user. The metadata could not…
- The metadata could not be encrypted with the metadata key id
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/b8b5070d00f6c87a.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/Metadata/src/Service/Migration/MigrateAllV4FoldersToV5Service.php:158
* @param \Passbolt\Folders\Model\Entity\Folder $folder Folder entity.
* @return void
*/
private function migratePersonal(MetadataFolderDto $dto, Folder $folder): void
{
$metadataArray = $dto->getClearTextMetadata();
/** @var \App\Model\Entity\Permission $permission */
$permission = $folder->get('permissions')[0];
$user = $permission->user;
if (is_null($user)) {
$msg = __('No user provided.') . ' ';
$msg .= __('The metadata could not be encrypted for permission id: {0}.', $permission->id);
throw new InternalErrorException($msg);
}
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->updateFolder($folder, [
'name' => null,
'metadata' => $metadataEncrypted,View on GitHub (pinned to 31c1bbc10f)