passbolt/passbolt_api · critical · CakeException
PHP Gnupg library is not installed.
Error message
PHP Gnupg library is not installed.
What it means
The Gnupg OpenPGP backend requires the PHP gnupg extension (a wrapper around libgpgme). Its constructor calls extension_loaded('gnupg') and throws a CakeException immediately if the extension is absent, before any keyring operations can run. This is an environment/setup failure, not a data problem: the passbolt container or server was built without the extension or it was not enabled in the SAPI.
Solutions
- Install the extension: apt install php-gnupg (or pecl install gnupg after apt install libgpgme-dev) and restart the PHP SAPI (php-fpm/apache).
- Verify with php -m | grep gnupg and, for the web SAPI, a phpinfo() page or php-fpm php.ini containing extension=gnupg.so.
- If multiple PHP versions are in play, install the extension for the exact version/SAPI running passbolt (e.g. php8.2-gnupg).
- Use the official passbolt Docker image or package repositories, which ship the gnupg extension preconfigured.
Example fix
// before (web SAPI php.ini has no gnupg) ; extension=gnupg.so // after extension=gnupg.so # then: sudo systemctl restart php8.2-fpm && php -m | grep gnupg
Defensive patterns
Strategy: type-guard
Validate before calling
if (!extension_loaded('gnupg')) {
throw new \RuntimeException(
'The PHP gnupg extension is required. Install php-gnupg and restart the SAPI.'
);
}
// also verify in the same SAPI that serves passbolt (php-fpm, not just CLI)
Type guard
function isGnupgAvailable(): bool
{
return extension_loaded('gnupg') && class_exists('gnupg');
}
Try / catch
try {
$backend = new \App\Utility\OpenPGP\Backends\Gnupg();
} catch (\Cake\Core\Exception\CakeException $e) {
// fail fast at bootstrap with a clear setup instruction
exit($e->getMessage() . PHP_EOL . 'Run: apt install php-gnupg && systemctl restart php-fpm');
}
Prevention
- Add php-gnupg to your deployment provisioning/infrastructure-as-code for every PHP version used.
- Check php -m | grep gnupg in a pre-deploy health check for the exact SAPI.
- Use official passbolt Docker images or distro packages that bundle the extension.
- After any PHP upgrade, re-verify extension presence before deploying.
When it happens
Trigger: Instantiating App\Utility\OpenPGP\Backends\Gnupg (directly or via OpenPGPBackend factory) on a PHP build where the gnupg extension is not compiled/loaded, e.g. stock php without php-gnupg installed, or the extension exists on CLI but not in the web server SAPI (different php.ini).
Common situations: Deploying passbolt on a self-managed server where php-gnupg (pecl/gnupg + libgpgme-dev) was never installed; switching PHP versions (e.g. via ondrej PPA or brew) and forgetting to reinstall the extension; Docker images built from a bare php base without the extension; CLI works but fpm/apache SAPI lacks the ini entry.
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
- Cannot generate a random UUID, some dependencies are…
- " " is not a valid search filter.
- " " is not a valid search filter. It is not a UTF8 string.
- " " is not a valid search filter. It should be between 1…
- " " is not a valid user filter.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/ae44fa68273033f7.
Report an issue: GitHub.
Appendix: source
Thrown at src/Utility/OpenPGP/Backends/Gnupg.php:59
class Gnupg extends OpenPGPBackend
{
/**
* Gpg object.
*
* @var \gnupg
*/
protected PhpGnupg $_gpg;
/**
* Constructor.
*
* @throws \Cake\Core\Exception\CakeException
*/
public function __construct()
{
parent::__construct();
if (!extension_loaded('gnupg')) {
throw new CakeException('PHP Gnupg library is not installed.');
}
if (Configure::read('passbolt.gpg.putenv')) {
putenv('GNUPGHOME=' . Configure::read('passbolt.gpg.keyring'));
}
$this->_gpg = new PhpGnupg();
$this->_gpg->seterrormode(GNUPG_ERROR_EXCEPTION);
}
/**
* Set a key for encryption.
*
* @param string $armoredKey ASCII armored key data
* @throws \Cake\Core\Exception\CakeException if the key cannot be used to encrypt
* @return bool true if success
*/
public function setEncryptKey(string $armoredKey): bool
{View on GitHub (pinned to 31c1bbc10f)