{"record":{"id":"65dab027456db024","repo":"MuntashirAkon/AppManager","slug":"failed-to-decrypt","errorCode":null,"errorMessage":"Failed to decrypt ","messagePattern":"Failed to decrypt ","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/OABConverter.java","lineNumber":261,"sourceCode":"            return metadataV2;\n        } catch (JSONException | IOException | CryptoException e) {\n            return ExUtils.rethrowAsBackupException(\"Could not parse JSON file.\", e);\n        }\n    }\n\n    private void backupApkFile() throws BackupException {\n        Path[] baseApkFiles;\n        try {\n            baseApkFiles = new Path[]{mBackupLocation.findFile(CryptoUtils.getAppropriateFilename(\n                    mSourceMetadata.apkName, mSourceCryptoMode))};\n        } catch (FileNotFoundException e) {\n            throw new BackupException(\"Could not get base.apk file.\", e);\n        }\n        // Decrypt APK file if needed\n        try {\n            baseApkFiles = ConvertUtils.decryptSourceFiles(baseApkFiles, mSourceCrypto, mSourceCryptoMode, mBackupItem);\n        } catch (IOException e) {\n            throw new BackupException(\"Failed to decrypt \" + Arrays.toString(baseApkFiles), e);\n        }\n        // baseApkFiles should be a singleton array\n        if (baseApkFiles.length != 1) {\n            throw new BackupException(\"Incorrect number of APK files: \" + baseApkFiles.length);\n        }\n        Path baseApkFile = baseApkFiles[0];\n        // Get certificate checksums\n        try {\n            String[] checksums = ConvertUtils.getChecksumsFromApk(baseApkFile, mDestMetadata.info.checksumAlgo);\n            for (int i = 0; i < checksums.length; ++i) {\n                mChecksum.add(CERT_PREFIX + i, checksums[i]);\n            }\n        } catch (Exception ignore) {\n        }\n        // Backup APK file\n        String sourceBackupFilePrefix = BackupUtils.getSourceFilePrefix(getExt(mDestMetadata.info.tarType));\n        Path[] sourceFiles;\n        try {","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/OABConverter.java#L243-L279","documentation":"After locating the APK, backupApkFile() calls ConvertUtils.decryptSourceFiles() to decrypt the source APK if the source backup was encrypted. If decryption throws IOException (I/O failure, corrupt archive, wrong crypto setup), it is wrapped into this BackupException. The message is prefixed with \"Failed to decrypt \" plus the file list, indicating the APK could not be turned into a readable plaintext file for further processing.","triggerScenarios":"backupApkFile() calls ConvertUtils.decryptSourceFiles(baseApkFiles, mSourceCrypto, mSourceCryptoMode, mBackupItem) and it throws IOException at OABConverter.java:261 — e.g. unreadable/corrupt encrypted file or a failing crypto stream.","commonSituations":"Converting an encrypted OAndBackup backup with wrong or missing crypto parameters; truncated/corrupted encrypted APK due to interrupted backup or bad storage; crypto implementation/key mismatch between the app that encrypted and the converter.","solutions":["Verify the source backup's crypto mode and credentials match how the backup was actually encrypted; supply the correct CryptoUtils setup.","Check the encrypted APK file for corruption (size, readability) and re-copy it from a healthy backup.","If the source is not encrypted, ensure mSourceCryptoMode reflects that so decryption is skipped rather than attempted.","Free up storage/verify write permissions for the backup item's working directories — I/O errors during decryption are often disk-related."],"exampleFix":"// before: converting with default (no) crypto while source is encrypted\n// OABConverter converter = new OABConverter(...); // mSourceCryptoMode unset\n// after: supply the correct source crypto mode so decryption succeeds\n// converter.setSourceCryptoMode(CryptoUtils.MODE_GCM); // matches the backup","handlingStrategy":"try-catch","validationCode":"Path encryptedApk = backupLocation.findFile(expectedName);\nif (sourceCrypto != null) {\n    if (!encryptedApk.isReadable() || encryptedApk.size() == 0) {\n        throw new IOException(\"Encrypted APK unreadable or empty: \" + encryptedApk);\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    converter.convert(...);\n} catch (BackupException e) {\n    if (e.getMessage().startsWith(\"Failed to decrypt\")) {\n        Log.e(TAG, \"Decryption failed; check source crypto params and file integrity\", e.getCause());\n    }\n}","preventionTips":["Supply the exact crypto parameters used when the source backup was encrypted.","Check free disk space before decryption — output is written to a working dir.","Validate encrypted files are complete (not truncated by interrupted transfers)."],"tags":["android","backup","encryption","decryption","io"],"backgroundTag":"file-read-failed","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"}