passbolt/passbolt_api · error · InternalErrorException

No user provided. The metadata could not be encrypted for…

Error message

No user provided. The metadata could not be encrypted for permission id: {0}.

What it means

Thrown in migratePersonal() when the resource's sole permission references a user that is not present (permission->user is null). The service needs a user's OpenPGP key to encrypt the resource metadata with a user key, so without a user it cannot proceed. The error aborts migration for that resource and is recorded in the result errors array.

Solutions

  1. Reassign the permission to an existing active user, or delete the orphaned permission and re-create ownership, then re-run migration.
  2. Delete the orphaned resource if it is no longer needed, then re-run migration.
  3. Find orphaned permissions ahead of time: SELECT permissions rows whose aro_foreign_key is absent from users, and fix them before migrating.
  4. Enable user retention (soft delete) or cleanup policies that reassign resources before removing users.

Example fix

// before: permission aro_foreign_key = <deleted-user-id>
// after: point it at an active user
UPDATE permissions SET aro_foreign_key = '<active-user-id>' WHERE id = '<permission-id>';
Defensive patterns

Strategy: validation

Validate before calling

// before migrating, find permissions pointing at missing users
$orphanPerms = $permissionsTable->find()
    ->leftJoinWith('Users')
    ->where(['Permissions.aro' => 'User', 'Users.id IS' => null])
    ->all();

Type guard

$user = $permission->user ?? null;
if (!$user instanceof \App\Model\Entity\User) { skip($resource); }

Prevention

When it happens

Trigger: migrate() -> migratePersonal() on a resource with exactly one permission that is not a group permission, where the permission's aro_foreign_key points to a user that no longer exists (deleted user, hard-deleted row) so the Users.Gpgkeys contain returns null for it.

Common situations: Instances where users were deleted without reassigning ownership of their personal resources; referential integrity gaps after manual DB edits or restores; permissions left pointing at soft/hard-removed accounts.

Understand the failure class

Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/fd745a5c3b93fc32. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/Metadata/src/Service/Migration/MigrateAllV4ResourcesToV5Service.php:162

    /**
     * @param \Passbolt\Metadata\Model\Dto\MetadataResourceDto $dto DTO.
     * @param \App\Model\Entity\Resource $resource Resource entity.
     * @return void
     * @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);
        }

View on GitHub (pinned to 31c1bbc10f)