{"record":{"id":"a25a69dc3bdec7bf","repo":"passbolt/passbolt_api","slug":"can-not-upgrade-please-upgrade-to-the-latest-1-x-version","errorCode":null,"errorMessage":"Can not upgrade. Please upgrade to the latest 1.x version first and retry. See https://help.passbolt.com/hosting/update.","messagePattern":"Can not upgrade\\. Please upgrade to the latest 1\\.x version first and retry\\. See https://help\\.passbolt\\.com/hosting/update\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"config/Migrations/20170830064410_V162InitialMigration.php","lineNumber":59,"sourceCode":"        foreach ($tables as $table) {\n            $exists = $this->hasTable($table);\n            if ($exists) {\n                $tableCount++;\n            }\n        }\n        // If this is an upgrade from v1\n        if ($tableCount > 0 && $tableCount < sizeof($tables)) {\n            throw new Exception('Can not upgrade. Some tables are missing.');\n        }\n\n        // If this is an upgrade from v1\n        if ($tableCount > 0) {\n            // Check the latest 1.x migration is done\n            $latestMigrationName = 'Migration_1_6_1';\n            $schemaMigrationResult = $this->query(\"SELECT * FROM schema_migrations WHERE class='$latestMigrationName'\");\n            $schemaMigrationRows = $schemaMigrationResult->fetchAll();\n            if (!count($schemaMigrationRows)) {\n                throw new Exception('Can not upgrade. Please upgrade to the latest 1.x version first and retry. See https://help.passbolt.com/hosting/update.');\n            }\n        }\n\n        // Reset the collation just in case\n        if ($this->getAdapter()->getAdapterType() !== \"pgsql\") {\n            $this->execute('ALTER DATABASE `' . $databaseName . '` COLLATE utf8mb4_unicode_ci');\n       }\n\n\n        // If this is an upgrade from v1\n        if ($tableCount > 0) {\n            // Alter collation\n            foreach ($tables as $table) {\n                $this->execute('ALTER TABLE ' . $table . ' COLLATE utf8mb4_unicode_ci');\n            }\n\n            return;\n        }","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/config/Migrations/20170830064410_V162InitialMigration.php#L41-L77","documentation":"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.","triggerScenarios":"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.","commonSituations":"Fingerprint typo/case mismatch against keyring contents; key removed from GNUPGHOME (e.g. recreated container); stale fingerprint in config after key regeneration; wrong passphrase.","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."],"exampleFix":"// before\n$gpg->setDecryptKeyFromFingerprint($staleFingerprint, $pass);\n// after\n$fingerprint = $gpg->importKeyIntoKeyring($armoredPrivateKey);\n$gpg->setDecryptKeyFromFingerprint($fingerprint, $correctPass);","handlingStrategy":"validation","validationCode":"$keys = shell_exec('GNUPGHOME=' . $home . ' gpg --list-keys --with-colons ' . escapeshellarg($fingerprint));\nif ($keys === null || trim($keys) === '') {\n    throw new InvalidArgumentException('Fingerprint not present in keyring: ' . $fingerprint);\n}\n","typeGuard":"function isFingerprint(string $f): bool {\n    return (bool) preg_match('/^[0-9A-F]{40}$/i', str_replace(' ', '', $f));\n}\n","tryCatchPattern":"try {\n    $gpg->setDecryptKeyFromFingerprint($fp, $pass);\n} catch (\\Cake\\Core\\Exception\\Exception $e) {\n    $this->log('adddecryptkey failed for ' . $fp . ': ' . $e->getMessage());\n    throw new ServerKeyConfigurationException(previous: $e);\n}\n","preventionTips":["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."],"tags":["openpgp","gnupg","decryption","fingerprint"],"backgroundTag":"invalid-argument-value","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}