passbolt/passbolt_api · critical · Cake\Http\Exception\InternalErrorException
The OpenPGP server key defined in the config cannot be used…
Error message
The OpenPGP server key defined in the config cannot be used to decrypt.
What it means
setServerKey imports the configured OpenPGP server key into the GnuPG keyring and registers it as decrypt/sign key during authenticator init. If any of those gnupg operations throws, the message is prefixed with 'The OpenPGP server key defined in the config cannot be used to decrypt.' plus the underlying exception message, and rethrown as InternalErrorException. The JWT flow cannot proceed without a usable server key.
Solutions
- Read the appended underlying exception message in the response/log — it names the exact gnupg failure.
- Verify the server key fingerprint and passphrase in config match the actual key files, and that both public and private key files exist and are readable.
- Regenerate or re-import the server key into the keyring (e.g. passbolt serverkey commands / gpg --import as the web user).
- Check the GNUPGHOME directory (~/.gnupg of the web-server user) exists, is writable, and gpg binary is installed.
- Ensure the passphrase in config is correct for the private key.
Example fix
// before (config): wrong fingerprint/passphrase
'fingerprint' => 'ABCD1234...',
'passphrase' => '',
// after: matching values for the imported key
'fingerprint' => strtoupper(str_replace(' ', '', $realFingerprint)),
'passphrase' => $actualKeyPassphrase Defensive patterns
Strategy: validation
Validate before calling
// healthcheck before auth flows
const ok = await fetch('/healthcheck/status.json').then(r => r.json());
if (!ok.body.gpg) throw new Error('Server GPG key not functional — fix config/keyring first'); Try / catch
try { await jwtLogin(); } catch (e) { if (e.message.includes('cannot be used to decrypt')) reportServerConfigIssue(e.message); else throw e; } Prevention
- Run the passbolt healthcheck after every deployment to validate the server key.
- Keep server key files and config fingerprint/passphrase in sync (config as code).
- Verify GNUPGHOME ownership/permissions for the web-server user after OS upgrades.
- Test key import with gpg CLI as the web user before switching environments.
When it happens
Trigger: JWT authentication bootstrap when: the server key fingerprint/passphrase in config is wrong; the key files (serverkey.asc / serverkey_private.asc) are missing or unreadable; the key cannot be imported into the keyring; the passphrase is incorrect; GnuPG is missing or the GNUPGHOME is not writable.
Common situations: Fresh deployments where `passbolt create_user`/serverkey generation step was skipped; wrong 'passbolt.gpg.keyring' or JWT server key config after migrating servers; keyring permission issues under the web-server user (www-data); passphrase changed in config but not on the key.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- The domain is invalid. Expected
- The OpenPGP server key defined in the config cannot be used…
- The OpenPGP server key defined in the config cannot be used…
- The OpenPGP server key defined in the config cannot be used…
- The OpenPGP server key defined in the config is not found…
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/6864cfbb00c6a215.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/JwtAuthentication/src/Authenticator/GpgJwtAuthenticator.php:220
$this->assertServerFingerprint($fingerprint);
// Check if config contains valid passphrase
$passphrase = Configure::read('passbolt.gpg.serverKey.passphrase');
$this->assertServerPassphrase($passphrase);
// set the key to be used for decrypting
try {
$this->gpg->setSignKeyFromFingerprint($fingerprint, $passphrase);
$this->gpg->setDecryptKeyFromFingerprint($fingerprint, $passphrase);
} catch (Exception $exception) {
try {
$this->gpg->importServerKeyInKeyring();
$this->gpg->setSignKeyFromFingerprint($fingerprint, $passphrase);
$this->gpg->setDecryptKeyFromFingerprint($fingerprint, $passphrase);
} catch (Exception $exception) {
$msg = __('The OpenPGP server key defined in the config cannot be used to decrypt.') . ' ';
$msg .= $exception->getMessage();
throw new InternalErrorException($msg, 500, $exception);
}
}
}
/**
* Set user key
*
* @throws \Cake\Http\Exception\BadRequestException if the user data is not valid
* @throws \Cake\Http\Exception\InternalErrorException if the user key cannot be loaded
* @return void
*/
public function setUserKey(): void
{
try {
$this->gpg->setVerifyKeyFromFingerprint($this->user->gpgkey->fingerprint);
$this->gpg->setEncryptKeyFromFingerprint($this->user->gpgkey->fingerprint);
} catch (Exception $exception) {
// Try to import the key in keyring againView on GitHub (pinned to 31c1bbc10f)