passbolt/passbolt_api · critical · InternalErrorException
The OpenPGP public key file '$publicKeyFileName' is not…
Error message
The OpenPGP public key file '$publicKeyFileName' is not readable.
What it means
verifyGet performs an is_readable() check on the configured public key file. When the file exists but the web-server process lacks read permission, an InternalErrorException stating the key file is not readable is thrown, since GPGAuth clients cannot be served the key.
Solutions
- chown the key file to the web-server user (e.g. chown www-data:www-data serverkey.asc) and chmod 640/644
- Verify readability as the runtime user: sudo -u www-data cat <path-to-serverkey.asc>
- Fix SELinux/AppArmor contexts (e.g. restorecon / chcon) if a MAC policy blocks the read
Example fix
// before -rw------- root root /etc/passbolt/gpg/serverkey.asc // after chown www-data:www-data /etc/passbolt/gpg/serverkey.asc chmod 640 /etc/passbolt/gpg/serverkey.asc
Defensive patterns
Strategy: validation
Validate before calling
// deploy-time pre-check (run as the web user) sudo -u www-data test -r /path/to/serverkey.asc || echo 'NOT READABLE';
Type guard
const keyFileReadable = (p?: string): p is string => typeof p === 'string' && fs.accessSync(p, fs.constants.R_OK) === undefined;
Try / catch
try { await fetch('/auth/verify.json'); } catch (e) {
if (e.status === 500 && /is not readable/.test(e.message)) { fixOwnershipAndPermissions(); }
} Prevention
- chown key files to the PHP-FPM user at deploy time
- Check readability as the runtime user, not root
- Update SELinux/AppArmor contexts when relocating keys
- Include a permissions check in healthcheck/CI scripts
When it happens
Trigger: GET /auth/verify.json where serverkey.asc exists but is owned by root (or another user) with permissions denying read access to the PHP-FPM/www-data process; SELinux/AppArmor blocking read; directory missing execute permission.
Common situations: Manually copying keys as root without chown/chmod; container images where the key was COPY'd with restrictive modes; hardened hosts with SELinux contexts not updated for the new key location.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- The OpenPGP server key defined in the config cannot be…
- The config for the server private key passphrase is invalid.
- A valid OpenPGP key must be provided.
- Could not import the user OpenPGP key.
- Could not read the file
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/00e9e5bb86ac9831.
Report an issue: GitHub.
Appendix: source
Thrown at src/Controller/Auth/AuthVerifyController.php:56
*
* @return void
*/
public function verifyGet()
{
$this->assertJson();
$configMissing = (Configure::read('passbolt.gpg.serverKey.public') === null);
$configMissing = ($configMissing || Configure::read('passbolt.gpg.serverKey.public') === null);
if ($configMissing) {
$msg = __('The OpenPGP public key information was not found in config.');
throw new InternalErrorException($msg);
}
$publicKeyFileName = Configure::read('passbolt.gpg.serverKey.public');
if (!file_exists($publicKeyFileName)) {
throw new InternalErrorException('The OpenPGP public key for this passbolt instance was not found.');
}
if (!is_readable($publicKeyFileName)) {
throw new InternalErrorException("The OpenPGP public key file '$publicKeyFileName' is not readable.");
}
$key = [
'fingerprint' => Configure::read('passbolt.gpg.serverKey.fingerprint'),
'keydata' => file_get_contents($publicKeyFileName),
];
$this->success(__('The operation was successful.'), $key);
}
}
View on GitHub (pinned to 31c1bbc10f)