passbolt/passbolt_api · error · InternalErrorException
The OpenPGP user key cannot be found.
Error message
The OpenPGP user key cannot be found. {exception message} What it means
setKeyForVerify throws InternalErrorException when it cannot load the Gpgkey of the user identified by modified_by to configure the OpenPGP backend for signature verification. The lookup on the gpgkeys table with firstOrFail() found no record (or the query failed), so verification of the metadata private key signature cannot proceed.
Solutions
- Find the user id in the error message and check whether the user and their gpgkeys row still exist
- If the user was deleted, correct modified_by on the metadata_private_keys/metadata_keys row to an existing admin, or restore the user/key from backup
- If the gpgkeys row is missing but the user exists, have the user complete setup or re-register their OpenPGP key
- Null out/normalize modified_by data via a migration if it references historical deleted users
Defensive patterns
Strategy: validation
Validate before calling
$user = $usersTable->find()->where(['id' => $modifiedBy])->first();
$gpg = $user ? $gpgkeysTable->find()->where(['user_id' => $modifiedBy])->first() : null;
if (!$user || !$gpg) {
throw new \DomainException("modified_by {$modifiedBy} has no user/gpg key; fix data before sharing.");
} Type guard
if (!is_string($modifiedBy) || !preg_match('/^[a-f0-9-]{36}$/i', $modifiedBy)) { return; } Try / catch
try {
$service->shareMetadataKeysWithUser($uac, $userIds, $keyId);
} catch (MetadataKeyShareException $e) {
if (str_contains($e->getMessage(), 'OpenPGP user key cannot be found')) {
// reassign modified_by or restore the deleted user/key before retrying
}
} Prevention
- Prefer soft-deleting users so their gpgkeys rows remain for signature verification
- Never null/void modified_by via raw SQL when editing metadata keys
- After user deletion, audit metadata keys/rows referencing the deleted id
- Back up gpgkeys before destructive user cleanup
When it happens
Trigger: shareMetadataKeyWithUser passes serverMetadataPrivateKey->modified_by to setKeyForVerify; if that user id has no row in gpgkeys (user deleted, key never generated, orphaned modified_by referencing a removed user) or the query throws, this error fires with the underlying message appended.
Common situations: modified_by points to a user deleted via cascade or hard delete that left gpgkeys orphaned/missing; a metadata key created by a script/bypassing ORM so modified_by is invalid; user deleted but their metadata key edits remain.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- The subscription key cannot be verified.
- A valid OpenPGP key must be provided.
- A valid OpenPGP key must be provided.
- A value for the theme should be provided.
- An OpenPGP key must be provided.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/7e1b2f2455fb31c6.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/Metadata/src/Service/MetadataKeyShareDefaultService.php:217
private function setKeyForVerify(OpenPGPBackend $gpg, ?string $createdBy = null): OpenPGPBackend
{
// Use server key if no user is defined in createdBy
if ($createdBy === null) {
return $this->setVerifyKeyWithServerKey($gpg);
}
// User key if createdBy is a user
try {
$usersTable = TableRegistry::getTableLocator()->get('Gpgkeys');
/** @var \App\Model\Entity\Gpgkey $userKey */
$userKey = $usersTable->find()
->where(['user_id' => $createdBy])
->orderBy(['created' => 'DESC'])
->firstOrFail();
} catch (Exception $exception) {
$msg = __('The OpenPGP user key cannot be found.') . ' ';
$msg .= $exception->getMessage();
throw new InternalErrorException($msg, 500, $exception);
}
return $this->setVerifyKeyWithUserKey($gpg, $userKey);
}
}
View on GitHub (pinned to 31c1bbc10f)