passbolt/passbolt_api · critical · InternalErrorException
Could not import the user OpenPGP key.
Error message
Could not import the user OpenPGP key.
What it means
GpgkeysHealthcheckService::initUserKey() tries to load the user's OpenPGP key into the GnuPG keyring and set it as encryption key. If the first attempt fails and the re-import plus key selection also throws, it wraps the failure in this InternalErrorException (HTTP 500).
Solutions
- Check the GNUPGHOME env/path permissions for the PHP/web server user
- Run the passbolt healthcheck (gpg section) to diagnose keyring state
- Delete and re-import the problematic key into the server keyring
- Verify the key fingerprint stored in gpgkeys table matches a key actually importable
- Ensure php-gnupg and gpg binary versions are compatible
Defensive patterns
Strategy: fallback
Validate before calling
// operator-side: verify keyring health before hitting the app bin/cake passbolt healthcheck --filter=gpg
Try / catch
try {
await healthcheckEndpoint();
} catch (e) {
if (e.response?.status === 500) {
// inspect GNUPGHOME permissions and re-import user key server-side
}
throw e;
} Prevention
- Ensure GNUPGHOME is writable by the web/PHP user
- Monitor healthcheck gpg section in CI or cron
- Re-import user keys after server or keyring migrations
- Keep php-gnupg and gpg versions compatible with passbolt requirements
When it happens
Trigger: canEncrypt() is called for a user whose armored key is not (or cannot be) imported into the server's GNUPGHOME keyring, e.g. corrupt keyring, missing key file, or fingerprint mismatch.
Common situations: GNUPGHOME directory wrong or unreadable by the web server user; keyring corrupted or on read-only storage; user's key was deleted from keyring; gpg extension keybox version issues after server migration.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- 500
- 500
- The key cannot be used to encrypt.
- The SCIM settings could not be decrypted with the server…
- The SCIM settings could not be encrypted with the server…
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/813df22d2b61df42.
Report an issue: GitHub.
Appendix: source
Thrown at src/Service/Gpgkeys/GpgkeysHealthcheckService.php:186
/**
* Set user key for encryption and import it in the keyring if needed
*
* @param string $fingerprint fingerprint
* @param string $armored armored
* @throws \Cake\Http\Exception\InternalErrorException when the key is not valid
* @return void
*/
private function initUserKey(string $fingerprint, string $armored): void
{
try {
$this->gpg->setEncryptKeyFromFingerprint($fingerprint);
} catch (CakeException $exception) {
// Try to import the key in keyring again
try {
$this->gpg->importKeyIntoKeyring($armored);
$this->gpg->setEncryptKeyFromFingerprint($fingerprint);
} catch (CakeException $exception) {
throw new InternalErrorException('Could not import the user OpenPGP key.', 500, $exception);
}
}
}
/**
* @param \App\Model\Entity\Gpgkey $gpgkey Gpgkey to assess
* @return void
*/
private function isKeyExpired(Gpgkey $gpgkey): void
{
if ($gpgkey->isExpired()) {
$msg = __('Key expired: {0}.', $gpgkey->fingerprint);
$this->checks[self::CHECK_IS_NOT_EXPIRED]->fail()->addDetail($msg, Healthcheck::STATUS_ERROR);
} else {
$msg = __('Expiration date valid for key {0}.', $gpgkey->fingerprint);
$this->checks[self::CHECK_IS_NOT_EXPIRED]->addDetail($msg, Healthcheck::STATUS_SUCCESS);
}
}View on GitHub (pinned to 31c1bbc10f)