{"record":{"id":"aea79eeb57e5c6f4","repo":"MuntashirAkon/AppManager","slug":"master-key-existed-when-the-checksum-was-made-but-now-it","errorCode":null,"errorMessage":"Master key existed when the checksum was made but now it doesn't.","messagePattern":"Master key existed when the checksum was made but now it doesn't\\.","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java","lineNumber":263,"sourceCode":"                    \"\\nFile: \" + metadataFile +\n                    \"\\nFound: \" + checksum +\n                    \"\\nRequired: \" + mChecksum.get(metadataFile.getName()));\n        }\n    }\n\n    private void checkMasterKey() throws BackupException {\n        if (true) {\n            // TODO: 6/2/22 MasterKey may not actually be necessary.\n            return;\n        }\n        String oldChecksum = mChecksum.get(MASTER_KEY);\n        Path masterKey;\n        try {\n            masterKey = KeyStoreUtils.getMasterKey(mUserId);\n        } catch (FileNotFoundException e) {\n            if (oldChecksum == null) return;\n            else\n                throw new BackupException(\"Master key existed when the checksum was made but now it doesn't.\");\n        }\n        if (oldChecksum == null) {\n            throw new BackupException(\"Master key exists but it didn't exist when the backup was made.\");\n        }\n        String newChecksum = DigestUtils.getHexDigest(mBackupInfo.checksumAlgo, masterKey.getContentAsString().getBytes());\n        if (!newChecksum.equals(oldChecksum)) {\n            throw new BackupException(\"Checksums for master key did not match.\");\n        }\n    }\n\n    private void restoreApkFiles() throws BackupException {\n        if (!mBackupFlags.backupApkFiles()) {\n            throw new BackupException(\"APK restore is requested but backup doesn't contain any source files.\");\n        }\n        Path[] backupSourceFiles = mBackupItem.getSourceFiles();\n        if (backupSourceFiles.length == 0) {\n            // No source backup found\n            throw new BackupException(\"Source restore is requested but there are no source files.\");","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java#L245-L281","documentation":"checkMasterKey() compares the crypto master key that currently exists in the keystore (per user) against the master-key checksum recorded when the backup was made. If the recorded checksum exists but KeyStoreUtils.getMasterKey() now throws FileNotFoundException, the code concludes the key was deleted since the backup and throws this BackupException. Note: this method currently returns early (line 252 `if (true) return;` with a TODO), so in this code version it is unreachable, but the intent is keystore-key lifecycle mismatch detection.","triggerScenarios":"mChecksum contains an entry for MASTER_KEY (the backup recorded that a master key existed), yet KeyStoreUtils.getMasterKey(mUserId) throws FileNotFoundException during a restore — the keystore key file/key for that user is gone.","commonSituations":"The user cleared App Manager data or Android keystore credentials between backup and restore; the device was reset; a different user ID was passed so the per-user key cannot be found; backups restored onto a new device where the key was never provisioned.","solutions":["Restore onto a device/profile where the same keystore master key still exists — i.e. the same device and user the backup was made on.","Regenerate the keystore master key, but be aware encrypted backups made with the old key cannot be decrypted; re-create backups after regeneration.","Verify you are restoring with the same mUserId as when the backup was created; the key lookup is per-user.","Use a newer App Manager build: the method is disabled via an early return (TODO 6/2/22), so upgrading avoids this hard failure."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Pre-check keystore key existence before restore:\ntry {\n    KeyStoreUtils.getMasterKey(userId);\n} catch (FileNotFoundException e) {\n    if (checksums.get(MASTER_KEY) != null) {\n        // key is gone: restore on original device/profile or recreate backup\n    }\n}","typeGuard":null,"tryCatchPattern":"try { restoreOp.runRestore(); } catch (BackupException e) {\n    if (e.getMessage().contains(\"Master key existed when the checksum was made\")) {\n        // alert: keystore key lost; encrypted backup undecryptable on this device\n    }\n}","preventionTips":["Do not clear App Manager data or keystore credentials between backup and restore.","Keep backups and their keys on the same device/user profile.","Prefer unencrypted backups when cross-device restore is planned."],"tags":["android","keystore","backup","encryption"],"backgroundTag":"file-not-found","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}