passbolt/passbolt_api · critical · Cake\Http\Exception\InternalErrorException
The config for the server private key fingerprint is not…
Error message
The config for the server private key fingerprint is not available or incomplete.
What it means
assertServerFingerprint validates that the configured server private key fingerprint is a string passing PublicKeyValidationService::isValidFingerprint. It throws InternalErrorException (500) because a missing/invalid server fingerprint is a server configuration problem, not a client mistake.
Solutions
- Set passbolt.gpg.serverKey.fingerprint in config/passbolt.php or passbolt.json to the full 40-character uppercase fingerprint
- Run `gpg --list-keys --fingerprint | grep -i passbolt` as the web server user and copy the fingerprint exactly
- Ensure the env variable (e.g. PASSBOLT_GPG_SERVER_KEY_FINGERPRINT) is defined in the deployment environment
- Re-run the server key import step (`passbolt install` key import or gpg --import serverkey.asc)`
- Run `ddev refresh` / `passbolt healthcheck` to confirm the server key config check passes
Example fix
// before config/passbolt.php
'serverKey' => ['fingerprint' => null],
// after
'serverKey' => ['fingerprint' => getenv('PASSBOLT_GPG_SERVER_KEY_FINGERPRINT')], // e.g. '0FC3E17C88AE067DD66B2D5A0B9BD6D9FA2C1A2F' Defensive patterns
Strategy: validation
Validate before calling
const fp = config.passbolt.gpg.serverKey.fingerprint;
if (typeof fp !== 'string' || !/^[A-F0-9]{40}$/.test(fp)) throw new Error('server key fingerprint config missing/invalid'); Type guard
function hasValidFingerprint(v) { return typeof v === 'string' && /^[0-9A-F]{40}$/.test(v); } Try / catch
try { await login(); } catch (e) { if (e.status === 500 && /fingerprint is not available/.test(e.message)) { await runServerKeySetup(); } } Prevention
- Set serverKey.fingerprint during provisioning and verify with passbolt healthcheck
- Use the full 40-char uppercase fingerprint
- Pin the fingerprint via env var so container rebuilds keep it
- Check config after every restore/migration
When it happens
Trigger: setServerKey runs during GPG JWT authentication bootstrap when passbolt.json / passbolt.php lacks passbolt.gpg.serverKey.fingerprint, or the value is not a valid 40-char hex fingerprint.
Common situations: Fresh install where `passbolt create_user`/key install steps were skipped; config import lost the serverKey block; fingerprint pasted with spaces or lowercase/short form; env var PASSBOLT_GPG_SERVER_KEY_FINGERPRINT not set in container.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- The config for the server private key passphrase is invalid.
- The config for the server private key passphrase is invalid.
- 500
- The file does not exist
- The GnuPG config for the server is not available or…
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/1f4971cf1b5f9d3d.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/JwtAuthentication/src/Authenticator/GpgJwtAuthenticator.php:362
);
} catch (Exception $exception) {
Log::error($exception->getMessage() . "\n" . $clearTextChallenge);
throw new BadRequestException(__('The challenge is invalid. Validation Failed.'));
}
return $verifyToken;
}
/**
* @param mixed $fingerprint fingerprint
* @throws \Cake\Http\Exception\InternalErrorException
* @return void
*/
public function assertServerFingerprint(mixed $fingerprint): void
{
if (!is_string($fingerprint) || !PublicKeyValidationService::isValidFingerprint($fingerprint)) {
$msg = __('The config for the server private key fingerprint is not available or incomplete.');
throw new InternalErrorException($msg);
}
}
/**
* @param mixed $passphrase passphrase
* @throws \Cake\Http\Exception\InternalErrorException
* @return void
*/
public function assertServerPassphrase(mixed $passphrase): void
{
if (!is_string($passphrase)) {
$msg = __('The config for the server private key passphrase is invalid.');
throw new InternalErrorException($msg);
}
}
/**
* @param mixed $userId uuidView on GitHub (pinned to 31c1bbc10f)