{"record":{"id":"c6f846bc79f9d966","repo":"MuntashirAkon/AppManager","slug":"destination-doesn-t-contain-any-backup","errorCode":null,"errorMessage":"Destination doesn't contain any backup.","messagePattern":"Destination doesn't contain any backup\\.","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/OABConverter.java","lineNumber":209,"sourceCode":"            JSONObject jsonObject = new JSONObject(jsonString);\n            metadataV2.label = jsonObject.getString(\"label\");\n            metadataV2.packageName = jsonObject.getString(\"packageName\");\n            metadataV2.versionName = jsonObject.getString(\"versionName\");\n            metadataV2.versionCode = jsonObject.getInt(\"versionCode\");\n            metadataV2.isSystem = jsonObject.optBoolean(\"isSystem\");\n            metadataV2.isSplitApk = false;\n            metadataV2.splitConfigs = ArrayUtils.emptyArray(String.class);\n            metadataV2.hasRules = false;\n            metadataV2.backupTime = jsonObject.getLong(\"lastBackupMillis\");\n            metadataV2.crypto = jsonObject.optBoolean(\"isEncrypted\") ? CryptoUtils.MODE_OPEN_PGP : CryptoUtils.MODE_NO_ENCRYPTION;\n            mSourceCryptoMode = metadataV2.crypto;\n            mSourceCrypto = CryptoUtils.setupCrypto(metadataV2);\n            metadataV2.apkName = new File(jsonObject.getString(\"sourceDir\")).getName();\n            // Flags\n            metadataV2.flags = new BackupFlags(BackupFlags.BACKUP_MULTIPLE);\n            int backupMode = jsonObject.optInt(\"backupMode\", MODE_UNSET);\n            if (backupMode == MODE_UNSET) {\n                throw new BackupException(\"Destination doesn't contain any backup.\");\n            }\n            if (backupMode == MODE_APK || backupMode == MODE_BOTH) {\n                if (mBackupLocation.hasFile(CryptoUtils.getAppropriateFilename(metadataV2.apkName,\n                        mSourceCryptoMode))) {\n                    metadataV2.flags.addFlag(BackupFlags.BACKUP_APK_FILES);\n                } else {\n                    throw new BackupException(\"Destination doesn't contain any APK files.\");\n                }\n            }\n            if (backupMode == MODE_DATA || backupMode == MODE_BOTH) {\n                boolean hasBackup = false;\n                if (mBackupLocation.hasFile(CryptoUtils.getAppropriateFilename(mPackageName + \".zip\",\n                        mSourceCryptoMode))) {\n                    metadataV2.flags.addFlag(BackupFlags.BACKUP_INT_DATA);\n                    hasBackup = true;\n                }\n                if (mBackupLocation.hasFile(EXTERNAL_FILES) && mBackupLocation.findFile(EXTERNAL_FILES).hasFile(\n                        CryptoUtils.getAppropriateFilename(mPackageName + \".zip\", mSourceCryptoMode))) {","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/OABConverter.java#L191-L227","documentation":"OABConverter parses an OAndBackup-style log file to rebuild backup metadata. The log's \"backupMode\" field is read with jsonObject.optInt(\"backupMode\", MODE_UNSET); if the key is absent or unreadable, backupMode stays MODE_UNSET and the converter refuses to continue because it cannot tell whether the source backup contains APKs, data, or both. This is a hard precondition: without a known backup mode the conversion would produce an incomplete or wrong App Manager backup.","triggerScenarios":"readLogFile() (called from convert()) encounters a log JSON object where key \"backupMode\" is missing, or its value parses to MODE_UNSET, i.e. jsonObject.optInt(\"backupMode\", MODE_UNSET) returns MODE_UNSET at OABConverter.java:209.","commonSituations":"Converting an OAndBackup log written by an older app version that did not record backupMode; a corrupted or truncated log file where the backupMode entry was lost; hand-edited log files; pointing the converter at a metadata/log file of a different format that lacks this key.","solutions":["Check the source log file and ensure it contains a numeric \"backupMode\" entry (0/1/2 per OAndBackup's MODE_APK/MODE_DATA/MODE_BOTH convention).","Re-create the backup with the original OAndBackup app so a fresh, complete log file is generated.","If the log is hand-edited or migrated, add the missing \"backupMode\" key with the correct value instead of leaving it absent.","Verify you are passing the correct log file (e.g. the per-package log, not a global index) to OABConverter.convert()."],"exampleFix":"// before: converting a log file that lacks the field\n// { \"packageName\": \"com.example\", \"apkName\": \"base.apk\" }\n\n// after: fix the source log JSON\n// { \"packageName\": \"com.example\", \"apkName\": \"base.apk\", \"backupMode\": 2 }","handlingStrategy":"validation","validationCode":"JSONObject log = readLogJson(logFile);\nif (!log.has(\"backupMode\") || log.optInt(\"backupMode\", MODE_UNSET) == MODE_UNSET) {\n    throw new IllegalArgumentException(logFile + \" has no valid backupMode; cannot convert\");\n}","typeGuard":"static boolean hasBackupMode(JSONObject log) {\n    return log.has(\"backupMode\") && log.optInt(\"backupMode\", Integer.MIN_VALUE) != Integer.MIN_VALUE;\n}","tryCatchPattern":"try {\n    converter.convert(...);\n} catch (BackupException e) {\n    if (e.getMessage().contains(\"doesn't contain any backup\")) {\n        Log.e(TAG, \"Log file missing backupMode: inspect \" + logFile, e);\n    }\n}","preventionTips":["Always generate backups with a current OAndBackup version that writes backupMode into the log.","Validate required log keys (packageName, apkName, backupMode) before invoking the converter.","Never hand-edit backup log files; regenerate them from the source app."],"tags":["android","backup","metadata","conversion","missing-field"],"backgroundTag":"missing-required-config-field","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"}