passbolt/passbolt_api · error · InvalidJwtKeyPairException
The JWT public key could not be extracted.
Error message
The JWT public key could not be extracted.
What it means
openssl_pkey_get_details($pk)['key'] is used to extract the PEM public key from the freshly generated private key; the code treats a missing 'key' entry as false and throws this error. Since $pk was just generated successfully, this almost always indicates an internal OpenSSL/library failure rather than user error.
Solutions
- Increase PHP memory_limit for CLI and retry the JWT key pair command
- Re-run generation — a transient OpenSSL failure may not reproduce
- Confirm openssl extension version compatibility with PHP (php -i | grep -A2 openssl)
- Check for non-zero OpenSSL error strings immediately after the call
Defensive patterns
Strategy: retry
Validate before calling
// precondition: openssl extension loaded and memory_limit adequate
if (ini_get('memory_limit') !== '-1' && \Cake\Utility\Text::parseBytes(ini_get('memory_limit')) < 134217728) { ini_set('memory_limit', '256M'); } Type guard
$details = openssl_pkey_get_details($pk); $publicKey = is_array($details) ? ($details['key'] ?? false) : false;
Try / catch
try { $service->createKeyPair(); } catch (InvalidJwtKeyPairException $e) { // retry once; persist if openssl_error_string() repeats } Prevention
- Retry key generation once on transient OpenSSL failures
- Keep PHP memory_limit >= 256M for CLI
- Use supported PHP/OpenSSL version pairings
When it happens
Trigger: openssl_pkey_get_details($pk) returns false or an array without 'key' immediately after a successful openssl_pkey_new/export in createKeyPair().
Common situations: Corrupted or exotic OpenSSL builds; memory exhaustion during key handling; non-RSA key types where 'key' handling differs; very low PHP memory_limit in CLI.
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
- The JWT private key could not be created.
- The JWT private key could not be written.
- The JWT public key could not be extracted.
- The JWT public key details could not be read.
- Attempt to access an expired verify token.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/3d2fa9308828ac14.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltCe/JwtAuthentication/src/Service/AccessToken/JwtKeyPairService.php:82
'digest_alg' => JwtTokenCreateService::JWT_ALG,
'private_key_bits' => $this->getKeyLength(),
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$secretKeyPath = $this->getSecretKeyPath();
$publicKeyPath = $this->getPublicKeyPath();
try {
$pk = openssl_pkey_new($config);
if ($pk === false) {
throw new Exception('The JWT private key could not be created.');
}
$export = openssl_pkey_export_to_file($pk, $secretKeyPath);
if ($export === false) {
throw new Exception('The JWT private key could not be written.');
}
$publicKey = openssl_pkey_get_details($pk)['key'] ?? false;
if ($publicKey === false) {
throw new Exception('The JWT public key could not be extracted.');
}
$export = file_put_contents($publicKeyPath, $publicKey);
if ($export === false) {
throw new Exception('The JWT public key could not be written.');
}
$permission = 0640;
$res = chmod($secretKeyPath, $permission);
if (!$res) {
throw new Exception("The permission of $secretKeyPath could not be set to $permission.");
}
$res = chmod($publicKeyPath, $permission);
if (!$res) {
throw new Exception("The permission of $publicKeyPath could not be set to $permission.");
}
} catch (Throwable $e) {
throw new InvalidJwtKeyPairException($e->getMessage());
}View on GitHub (pinned to 31c1bbc10f)