passbolt/passbolt_api · error · InternalErrorException
Could not import the user OpenPGP key.
Error message
Could not import the user OpenPGP key.
What it means
setEncryptKeyWithUserKey() first tries setEncryptKeyFromFingerprint($userKey->fingerprint); if the key is not in the GnuPG keyring it retries by importing armored_key via importKeyIntoKeyring() and setting the key again. If that fallback also throws, the InternalErrorException 'Could not import the user OpenPGP key.' (HTTP 500) is raised. The key data itself passed validation, but the GPG keyring refuses to store or use it.
Solutions
- Check the chained exception message in the log/debug output — it contains the underlying gnupg error explaining why the import or key selection failed.
- Verify the web-server user's GnuPG keyring permissions and GNUPGHOME directory (ownership, 700, readable keyring files) and re-run the operation.
- Manually test importing the armored key with gpg --import to see gnupg's own error for that key.
- Have the user re-generate or re-upload their key if the stored key is rejected by the installed gnupg version (e.g. keys using deprecated algorithms).
- If keyring corruption is suspected, rebuild the keyring (delete/recreate the gnupg homedir for the web user) and let passbolt re-import keys on demand.
Example fix
// before: relying on keyring having the key
$gpg->setEncryptKeyFromFingerprint($userKey->fingerprint);
// after: pre-check key presence and surface the gnupg error clearly
try {
$gpg->setEncryptKeyFromFingerprint($userKey->fingerprint);
} catch (Exception $e) {
$imported = $gpg->importKeyIntoKeyring($userKey->armored_key);
if (!$imported) {
throw new InternalErrorException(
__('The user key could not be imported into the keyring: {0}', $e->getMessage())
);
}
$gpg->setEncryptKeyFromFingerprint($userKey->fingerprint);
} Defensive patterns
Strategy: try-catch
Validate before calling
use App\Service\OpenPGP\PublicKeyValidationService;
if (!PublicKeyValidationService::parseAndValidatePublicKey($userKey->armored_key)) {
throw new BadRequestException('User armored key is not a valid public key.');
}
if (!is_dir(getenv('GNUPGHOME') ?: sys_get_temp_dir())) {
throw new RuntimeException('GnuPG homedir is not available.');
} Type guard
function isNonEmptyString(mixed $value): bool
{
return is_string($value) && $value !== '';
}
// use: isNonEmptyString($userKey->armored_key) && isNonEmptyString($userKey->fingerprint) Try / catch
try {
$gpg = $this->setEncryptKeyWithUserKey($gpg, $userKey);
} catch (InternalErrorException $e) {
$reason = $e->getPrevious()?->getMessage() ?? 'unknown gnupg error';
// e.g. keyring permission problem vs bad key data
$this->log(__('Keyring import failed for {0}: {1}', $userKey->fingerprint, $reason));
throw new InternalErrorException(
__('The user key could not be imported. Check the server GPG keyring: {0}', $reason)
);
} Prevention
- Preserve the web-server user's .gnupg directory (correct ownership/permissions, 700) across deployments and migrations.
- Keep gnupg versions consistent between environments; test key imports after OS upgrades.
- Log the chained previous exception (enable debug or wrap the call) so gnupg's real error is visible.
- Validate armored keys with PublicKeyValidationService before storing them.
- Have a recovery path to let users re-upload keys that gnupg rejects (expired keys, deprecated algorithms).
When it happens
Trigger: Calling setEncryptKeyWithUserKey() when the user's public key is absent from the server keyring AND the re-import of $userKey->armored_key fails (malformed armor despite passing validation, expired/revoked key rejected by gnupg, keyring permission or gnupg homedir issues, key already present with different fingerprint data).
Common situations: GnuPG homedir (e.g. /home/www-data/.gnupg) owned by wrong user or wrong permissions after server migration; different gnupg version on new server rejecting old key packets; keyring wiped/rebuilt (keyring dir deleted); armored key stored with broken line endings after a database import/export; corrupted key from third-party import scripts.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Could not validate user data.
- The key cannot be used to encrypt.
- A valid OpenPGP key must be provided.
- Could not import the user OpenPGP key.
- Could not import the user OpenPGP key.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/e590a8a5d8e43d78.
Report an issue: GitHub.
Appendix: source
Thrown at src/Service/OpenPGP/OpenPGPCommonUserOperationsTrait.php:57
try {
$this->assertUserKey($userKey);
} catch (Exception $exception) {
$msg = __('Could not validate user data.');
throw new InternalErrorException($msg, 500, $exception);
}
try {
$gpg->setEncryptKeyFromFingerprint($userKey->fingerprint);
} catch (Exception $exception) {
// Try to import the key in keyring again
try {
$gpg->importKeyIntoKeyring($userKey->armored_key);
$gpg->setEncryptKeyFromFingerprint($userKey->fingerprint);
} catch (Exception $exception) {
if (Configure::read('debug')) {
Log::error(json_encode($userKey));
}
$msg = __('Could not import the user OpenPGP key.');
throw new InternalErrorException($msg, 500, $exception);
}
}
return $gpg;
}
/**
* Get the OpenPGP Backend ready to verify with user key
*
* @param \App\Utility\OpenPGP\OpenPGPBackend $gpg for example OpenPGPBackendFactory::get()
* @param \App\Model\Entity\Gpgkey $userKey entity
* @return \App\Utility\OpenPGP\OpenPGPBackend backend configured to use user key to verify
* @throws \Cake\Http\Exception\InternalErrorException if the user key cannot be loaded
*/
protected function setVerifyKeyWithUserKey(OpenPGPBackend $gpg, Gpgkey $userKey): OpenPGPBackend
{
// Set encryption key as the one from the user
try {View on GitHub (pinned to 31c1bbc10f)