passbolt/passbolt_api · error · Exception
Can not upgrade. Please upgrade to the latest 1.x version…
Error message
Can not upgrade. Please upgrade to the latest 1.x version first and retry. See https://help.passbolt.com/hosting/update.
What it means
Thrown by Gnupg::setDecryptKeyFromFingerprint when gnupg_adddecryptkey() fails for a key that should already exist in the keyring, identified by fingerprint. Same failure family as setDecryptKey but without an import step: the key must already be present and usable with the given passphrase. The gnupg exception message is appended.
Solutions
- Run `gpg --list-keys --fingerprint` in the GNUPGHOME used by the app to confirm the key exists.
- Verify the passphrase is correct for that specific key.
- Re-import the private key (importKeyIntoKeyring / setDecryptKey) then retry.
- Confirm the configured fingerprint matches the current server key (no stale value).
- Check GNUPGHOME env var and directory ownership of the web server user.
Example fix
// before $gpg->setDecryptKeyFromFingerprint($staleFingerprint, $pass); // after $fingerprint = $gpg->importKeyIntoKeyring($armoredPrivateKey); $gpg->setDecryptKeyFromFingerprint($fingerprint, $correctPass);
Defensive patterns
Strategy: validation
Validate before calling
$keys = shell_exec('GNUPGHOME=' . $home . ' gpg --list-keys --with-colons ' . escapeshellarg($fingerprint));
if ($keys === null || trim($keys) === '') {
throw new InvalidArgumentException('Fingerprint not present in keyring: ' . $fingerprint);
}
Type guard
function isFingerprint(string $f): bool {
return (bool) preg_match('/^[0-9A-F]{40}$/i', str_replace(' ', '', $f));
}
Try / catch
try {
$gpg->setDecryptKeyFromFingerprint($fp, $pass);
} catch (\Cake\Core\Exception\Exception $e) {
$this->log('adddecryptkey failed for ' . $fp . ': ' . $e->getMessage());
throw new ServerKeyConfigurationException(previous: $e);
}
Prevention
- Import the private key (setDecryptKey) instead of relying on pre-provisioned keyrings in ephemeral environments.
- Normalize fingerprints (uppercase, strip spaces) before calling.
- Health-check the keyring at startup by listing secret keys.
- Keep fingerprint config in sync when regenerating keys.
When it happens
Trigger: Calling setDecryptKeyFromFingerprint($fingerprint, $passphrase) where the fingerprint is not in the keyring, the passphrase mismatches, or the key has no secret part usable for decryption.
Common situations: Fingerprint typo/case mismatch against keyring contents; key removed from GNUPGHOME (e.g. recreated container); stale fingerprint in config after key regeneration; wrong passphrase.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- A value for the theme should be provided.
- Can not upgrade. Some tables are missing.
- Decryption failed.
- The key was not found in the keyring
- The OpenPGP server key defined in the config cannot be used…
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/a25a69dc3bdec7bf.
Report an issue: GitHub.
Appendix: source
Thrown at config/Migrations/20170830064410_V162InitialMigration.php:59
foreach ($tables as $table) {
$exists = $this->hasTable($table);
if ($exists) {
$tableCount++;
}
}
// If this is an upgrade from v1
if ($tableCount > 0 && $tableCount < sizeof($tables)) {
throw new Exception('Can not upgrade. Some tables are missing.');
}
// If this is an upgrade from v1
if ($tableCount > 0) {
// Check the latest 1.x migration is done
$latestMigrationName = 'Migration_1_6_1';
$schemaMigrationResult = $this->query("SELECT * FROM schema_migrations WHERE class='$latestMigrationName'");
$schemaMigrationRows = $schemaMigrationResult->fetchAll();
if (!count($schemaMigrationRows)) {
throw new Exception('Can not upgrade. Please upgrade to the latest 1.x version first and retry. See https://help.passbolt.com/hosting/update.');
}
}
// Reset the collation just in case
if ($this->getAdapter()->getAdapterType() !== "pgsql") {
$this->execute('ALTER DATABASE `' . $databaseName . '` COLLATE utf8mb4_unicode_ci');
}
// If this is an upgrade from v1
if ($tableCount > 0) {
// Alter collation
foreach ($tables as $table) {
$this->execute('ALTER TABLE ' . $table . ' COLLATE utf8mb4_unicode_ci');
}
return;
}View on GitHub (pinned to 31c1bbc10f)