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

  1. Have the affected user upload an OpenPGP key (or restore their key) before running the migration.
  2. Exclude users without keys from migration targets and handle them separately.
  3. Ensure the query contains Gpgkeys under Permissions.Users so existing keys are hydrated.
  4. 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

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


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)