{"record":{"id":"78d1a2aed8d9ef1e","repo":"passbolt/passbolt_api","slug":"no-openpgp-key-found-for-the-user-the-metadata-could-not-be-78d1a2","errorCode":null,"errorMessage":"No OpenPGP key found for the user. The metadata could not be encrypted with the user id: {0}.","messagePattern":"No OpenPGP key found for the user\\. The metadata could not be encrypted with the user id: (.+?)\\.","errorType":"http","errorClass":"InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltEe/Tags/src/Service/Metadata/MigrateAllV4TagsToV5Service.php","lineNumber":211,"sourceCode":"     */\n    private function migratePersonal(MetadataTagDto $dto, Tag $tag): void\n    {\n        $metadataArray = $dto->getClearTextMetadata();\n        $users = $tag->get('users');\n\n        if (!is_array($users) || count($users) < 1) {\n            throw new InternalErrorException(__('No user found for the personal tag id: \"{0}\".', $tag->id));\n        }\n\n        /** @var \\App\\Model\\Entity\\User $user */\n        $user = $users[0];\n        if (is_null($user)) {\n            throw new InternalErrorException(__('User contain data missing for the tag id: \"{0}\".', $tag->id));\n        }\n        if (is_null($user->gpgkey)) {\n            $msg = __('No OpenPGP key found for the user.') . ' ';\n            $msg .= __('The metadata could not be encrypted with the user id: {0}.', $user->id);\n            throw new InternalErrorException($msg);\n        }\n\n        try {\n            $gpg = OpenPGPBackendFactory::get();\n            $gpg->clearKeys();\n            $gpg = $this->setSignKeyWithServerKey($gpg);\n            $gpg = $this->setEncryptKeyWithUserKey($gpg, $user->gpgkey);\n            $metadataClearText = json_encode($metadataArray, JSON_THROW_ON_ERROR);\n            $metadataEncrypted = $gpg->encrypt($metadataClearText, true);\n        } catch (Exception $exception) {\n            $msg = $exception->getMessage() . ' ';\n            $msg .= __('The metadata could not be encrypted with the user id: {0}.', $user->id);\n            throw new InternalErrorException($msg, 500, $exception);\n        }\n\n        $this->updateTag($tag, [\n            'slug' => null,\n            'metadata' => $metadataEncrypted,","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/Tags/src/Service/Metadata/MigrateAllV4TagsToV5Service.php#L193-L229","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n$tags = $this->Tags->find()->contain(['Users'])->all();\n// after\n$tags = $this->Tags->find()->contain(['Users' => ['Gpgkeys']])->all();","handlingStrategy":"validation","validationCode":"$keyless = $usersTable->find()\n    ->leftJoinWith('Gpgkeys')\n    ->where(['Gpgkeys.id IS NULL'])\n    ->all();\n// exclude tags owned by $keyless users from the migration batch","typeGuard":"function hasGpgKey(User $user): bool {\n    return $user->gpgkey !== null && $user->gpgkey->fingerprint !== null;\n}","tryCatchPattern":"try {\n    $service->migrate($uac, $batch);\n} catch (InternalErrorException $e) {\n    if (str_contains($e->getMessage(), 'No OpenPGP key found')) {\n        $this->log('Owner lacks GPG key; defer tag migration');\n    } else { throw $e; }\n}","preventionTips":["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"],"tags":["gpg","migration","tags"],"backgroundTag":"missing-credentials","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}