passbolt/passbolt_api · error · Cake\Core\Exception\CakeException
Can not decrypt without a key. Set a secret key first.
Error message
Can not decrypt without a key. Set a secret key first.
What it means
assertDecryptKey() is a precondition check for OpenPGP decryption in OpenPGPCommonAssertsTrait. It throws a CakeException when _decryptKeyFingerprint is empty, because the server's private (secret) key must be set via setDecryptKey() before any ciphertext can be decrypted.
Solutions
- Call setDecryptKey() with the server secret key fingerprint (and passphrase if protected) before decrypting.
- Verify the server private key is configured (config values/env) and the bootstrap that loads it runs in the failing context.
- Confirm the secret key is present in the keyring and readable by the process user.
Example fix
// before $plain = $gpg->decrypt($cipher); // throws: no decrypt key // after $gpg->setDecryptKey($serverKeyFingerprint, $serverKeyPassphrase); $plain = $gpg->decrypt($cipher);
Defensive patterns
Strategy: type-guard
Validate before calling
if (empty($serverKeyFingerprint)) {
throw new \RuntimeException('Server decrypt key is not configured.');
}
$gpg->setDecryptKey($serverKeyFingerprint, $passphrase); Type guard
function canDecrypt($gpg): bool {
return isset($gpg) && !empty($gpg->getDecryptKeyFingerprint());
} Try / catch
try {
$plain = $gpg->decrypt($cipher);
} catch (\Cake\Core\Exception\CakeException $e) {
if (str_contains($e->getMessage(), 'decrypt without a key')) {
// server key not loaded: fail loudly with a config-level message
throw new \RuntimeException('Server key not loaded into OpenPGP utility.', 0, $e);
}
throw $e;
} Prevention
- Load the server secret key in a shared bootstrap used by both web and CLI contexts.
- Add a startup check that the server key fingerprint config is present and the key is in the keyring.
- Document key setup as a prerequisite for any command that decrypts data.
When it happens
Trigger: Calling decrypt() (or code invoking assertDecryptKey) without setDecryptKey() having been called — e.g. a CLI command or service that builds an OpenPGP utility instance without loading the server's private key fingerprint.
Common situations: Server key not configured in environment/config so bootstrap skips setDecryptKey; running recovery/CLI scripts outside the web bootstrap; key rotation leaving decrypt key unset while data still encrypted with the old key.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Can not encrypt without a key. Set a public key first.
- Can not sign without a key. Set a sign key first.
- Can not upgrade. Please upgrade to the latest 1.x version…
- Can not upgrade. Some tables are missing.
- Can not verify without a key. Set a verification key first.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/dd7944f28fe8ced9.
Report an issue: GitHub.
Appendix: source
Thrown at src/Utility/OpenPGP/Traits/OpenPGPCommonAssertsTrait.php:107
* @return void
*/
public function assertEncryptKey(): void
{
if (empty($this->_encryptKeyFingerprint)) {
throw new CakeException('Can not encrypt without a key. Set a public key first.');
}
}
/**
* Check if a decrypt key is set
*
* @throws \Cake\Core\Exception\CakeException if no decryption key is set
* @return void
*/
public function assertDecryptKey(): void
{
if (empty($this->_decryptKeyFingerprint)) {
throw new CakeException('Can not decrypt without a key. Set a secret key first.');
}
}
}
View on GitHub (pinned to 31c1bbc10f)