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

  1. Check the GNUPGHOME env/path permissions for the PHP/web server user
  2. Run the passbolt healthcheck (gpg section) to diagnose keyring state
  3. Delete and re-import the problematic key into the server keyring
  4. Verify the key fingerprint stored in gpgkeys table matches a key actually importable
  5. 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

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


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)