{"record":{"id":"8d8f7c54dd722ed8","repo":"MuntashirAkon/AppManager","slug":"could-not-get-base-apk-file","errorCode":null,"errorMessage":"Could not get base.apk file.","messagePattern":"Could not get base\\.apk file\\.","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/OABConverter.java","lineNumber":255,"sourceCode":"            metadataV2.dataDirs = ConvertUtils.getDataDirs(mPackageName, mUserId, metadataV2.flags\n                    .backupInternalData(), metadataV2.flags.backupExternalData(), false);\n            metadataV2.tarType = Prefs.BackupRestore.getCompressionMethod();\n            metadataV2.keyStore = false;\n            metadataV2.installer = Prefs.Installer.getInstallerPackageName();\n            metadataV2.version = 2;  // Old version is used so that we know that it needs permission fixes\n            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            }","sourceCodeStart":237,"sourceCodeEnd":273,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/OABConverter.java#L237-L273","documentation":"In backupApkFile(), the converter tries to locate the actual APK file in the backup location using findFile() with the crypto-appropriate name derived from the source metadata's apkName. findFile() throws FileNotFoundException when the file does not exist, which is wrapped into this BackupException. It means the APK that the earlier metadata phase claimed to exist could not actually be found when the backup step ran.","triggerScenarios":"backupApkFile() (called from convert()) executes mBackupLocation.findFile(CryptoUtils.getAppropriateFilename(mSourceMetadata.apkName, mSourceCryptoMode)) and the file is missing, throwing FileNotFoundException at OABConverter.java:255.","commonSituations":"Race/deletion: the APK was removed from the backup dir between the metadata scan and the backup step; apkName in the source metadata differs from the on-disk filename (renamed, split APK names); wrong source crypto mode producing the wrong expected filename.","solutions":["Confirm the APK file matching the source metadata's apkName exists in the backup location before running the conversion.","Restore/re-copy the APK from the original OAndBackup backup if it was deleted.","Check mSourceCryptoMode: an encrypted source stores files under crypto-transformed names; a wrong mode yields a wrong lookup name.","Ensure apkName in the log matches the real file name (e.g. base.apk vs. an app-specific name)."],"exampleFix":"// before\n// backup/ contains \"base.apk\" but log says \"apkName\": \"app-release.apk\"\n// after: align names\n// \"apkName\": \"base.apk\"  (or rename the file to app-release.apk)","handlingStrategy":"try-catch","validationCode":"String expected = CryptoUtils.getAppropriateFilename(sourceMetadata.apkName, sourceCryptoMode);\nif (!backupLocation.hasFile(expected)) {\n    Log.w(TAG, \"APK missing before backup step: \" + expected);\n}","typeGuard":null,"tryCatchPattern":"try {\n    converter.convert(...);\n} catch (BackupException e) {\n    if (e.getMessage().startsWith(\"Could not get base.apk\")) {\n        Log.e(TAG, \"APK vanished or misnamed: \" + e.getCause(), e);\n    }\n}","preventionTips":["Do not modify the backup directory while a conversion is running.","Ensure apkName in metadata matches the actual on-disk file name.","Verify source crypto mode so findFile() looks up the right (possibly encrypted) name."],"tags":["android","backup","file-not-found","apk"],"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"}