{"record":{"id":"61b35a2f42f910c1","repo":"MuntashirAkon/AppManager","slug":"failed-to-get-crypto","errorCode":null,"errorMessage":"Failed to get crypto ","messagePattern":"Failed to get crypto ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/MetadataManager.java","lineNumber":167,"sourceCode":"        Path infoFile = backupFile.getInfoFile();\n        try (OutputStream outputStream = infoFile.openOutputStream()) {\n            outputStream.write(metadata.info.serializeToJson().toString(4).getBytes());\n            filenameChecksumMap.put(infoFile.getName(), DigestUtils.getHexDigest(\n                    metadata.info.checksumAlgo, infoFile));\n        } catch (JSONException e) {\n            throw new IOException(e.getMessage() + \" for file \" + infoFile, e);\n        }\n        return filenameChecksumMap;\n    }\n\n    private static void setCrypto(@NonNull BackupItems.BackupItem backupItem, @NonNull BackupMetadataV5.Info backupInfo) throws IOException {\n        if (!CryptoUtils.isAvailable(backupInfo.crypto)) {\n            throw new IOException(\"Mode \" + backupInfo.crypto + \" is currently unavailable.\");\n        }\n        try {\n            backupItem.setCrypto(backupInfo.getCrypto());\n        } catch (CryptoException e) {\n            throw new IOException(\"Failed to get crypto \" + backupInfo.crypto, e);\n        }\n    }\n}\n","sourceCodeStart":149,"sourceCodeEnd":171,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/MetadataManager.java#L149-L171","documentation":"MetadataManager.setCrypto wraps CryptoException from BackupItem.setCrypto into an IOException with the failing crypto mode name appended. It is thrown when the crypto engine accepted the mode as 'available' but actually instantiating/initializing it for the backup item fails. This blocks reading the backup metadata during a restore.","triggerScenarios":"readMetadata -> setCrypto calls backupItem.setCrypto(backupInfo.getCrypto()) and CryptoUtils throws CryptoException, e.g. key/password mismatch, missing crypto provider files (MasterCrypt/ECryptfs unavailable), or a corrupted encrypted header.","commonSituations":"Restoring a backup made with a password/keystore the user no longer has; Android version changed so the chosen crypto mode's kernel module (ecryptfs) is gone; backup json lists a mode whose key files were not restored.","solutions":["Verify the crypto mode recorded in backup.json is actually usable on this device (CryptoUtils.isAvailable passes but initialization fails — check the wrapped CryptoException cause)","Re-enter the correct password/key for the mode (most CryptoException cases stem from key derivation failure)","Move to a device/ROM that supports the mode (e.g. ecryptfs-enabled ROM) or re-create the backup with a supported mode","If the cause is missing key files, restore the crypto key material before retrying the restore"],"exampleFix":"// before\nbackupItem.setCrypto(backupInfo.getCrypto());\n// after\nif (CryptoUtils.isAvailable(backupInfo.crypto)) {\n    try {\n        backupItem.setCrypto(backupInfo.getCrypto());\n    } catch (CryptoException e) {\n        Log.e(TAG, \"Crypto init failed for mode \" + backupInfo.crypto, e);\n        throw new IOException(\"Failed to get crypto \" + backupInfo.crypto, e);\n    }\n}","handlingStrategy":"try-catch","validationCode":"if (!CryptoUtils.isAvailable(mode)) throw new IOException(\"Mode \" + mode + \" unavailable before metadata read\");","typeGuard":"boolean cryptoUsable(String mode) { return CryptoUtils.isAvailable(mode); }","tryCatchPattern":"try { readMetadata(...); } catch (IOException e) { if (e.getMessage() != null && e.getMessage().startsWith(\"Failed to get crypto\")) { promptForPasswordOrAbort(); } else throw e; }","preventionTips":["Always check CryptoUtils.isAvailable before attempting a restore","Keep backup passwords/keys stored alongside backup records","Test-restore on the target device/ROM before deleting the source backup"],"tags":["crypto","android","backup","restore"],"backgroundTag":"missing-credentials","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}