{"record":{"id":"dd5904ae23b26241","repo":"MuntashirAkon/AppManager","slug":"could-not-backup-data","errorCode":null,"errorMessage":"Could not backup data","messagePattern":"Could not backup data","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/TBConverter.java","lineNumber":368,"sourceCode":"            }\n\n            // Encrypt created backups and generate checksum\n            if (intSos != null) {\n                // Encrypt backups\n                Path[] newBackupFiles = mBackupItem.encrypt(intSos.getFiles().toArray(new Path[0]));\n                for (Path file : newBackupFiles) {\n                    mChecksum.add(file.getName(), DigestUtils.getHexDigest(mDestMetadata.info.checksumAlgo, file));\n                }\n            }\n            if (extSos != null) {\n                // Encrypt backups\n                Path[] newBackupFiles = mBackupItem.encrypt(extSos.getFiles().toArray(new Path[0]));\n                for (Path file : newBackupFiles) {\n                    mChecksum.add(file.getName(), DigestUtils.getHexDigest(mDestMetadata.info.checksumAlgo, file));\n                }\n            }\n        } catch (IOException e) {\n            throw new BackupException(\"Could not backup data\", e);\n        }\n    }\n\n    private BackupMetadataV2 readPropFile() throws BackupException {\n        try (InputStream is = mPropFile.openInputStream()) {\n            BackupMetadataV2 metadataV2 = new BackupMetadataV2();\n            Properties prop = new Properties();\n            prop.load(is);\n            metadataV2.label = prop.getProperty(\"app_label\");\n            metadataV2.packageName = mPackageName;\n            metadataV2.versionName = prop.getProperty(\"app_version_name\");\n            metadataV2.versionCode = Integer.parseInt(prop.getProperty(\"app_version_code\"));\n            metadataV2.isSystem = \"1\".equals(prop.getProperty(\"app_is_system\"));\n            metadataV2.isSplitApk = false;\n            metadataV2.splitConfigs = ArrayUtils.emptyArray(String.class);\n            metadataV2.hasRules = false;\n            metadataV2.backupTime = mBackupTime;\n            metadataV2.crypto = CryptoUtils.MODE_NO_ENCRYPTION;  // We only support no encryption mode for TB backups","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/TBConverter.java#L350-L386","documentation":"backupData() wraps the whole decompress->retar->encrypt/checksum pipeline in a try block; any IOException (read failure on the source archive, disk full, write failure to split outputs, encryption I/O errors) is rethrown as BackupException(\"Could not backup data\", e). It is the generic failure point of the TB conversion's data-copy stage.","triggerScenarios":"Any IOException inside backupData(): unreadable/corrupt source tar, storage full while writing SplitOutputStream segments, permission errors on the backup path, or failures while encrypting the produced split files.","commonSituations":"Insufficient free space on internal/external storage during large app data conversion; corrupted or truncated source .tar; SD card removed mid-operation; storage permission revoked; encryption key/keystore issues surfacing as I/O failures.","solutions":["Inspect the cause chain (getCause()) for the underlying IOException; fix that specific issue.","Free up storage space before converting; large app data can exceed available space.","Verify the source tar is not truncated (compare checksums/size with the original backup).","Re-check storage permissions and that the backup path is writable and mounted."],"exampleFix":"// before\ntry { converter.convert(backupDir); }\ncatch (BackupException e) { Log.e(TAG, \"failed\"); }\n// after\ntry { converter.convert(backupDir); }\ncatch (BackupException e) {\n    Log.e(TAG, \"convert failed\", e); // read the wrapped IOException\n    if (e.getCause() instanceof IOException && !hasFreeSpace(dir, requiredBytes)) {\n        // prompt user to free space, then retry\n    }\n}","handlingStrategy":"try-catch","validationCode":"long required = sourceTar.length() * 3L; // decompressed + retarred + encrypted estimate\nif (new File(destPath).getUsableSpace() < required) throw new IllegalStateException(\"Not enough free space\");","typeGuard":null,"tryCatchPattern":"try {\n    converter.convert(backupDir);\n} catch (BackupException e) {\n    Throwable cause = e.getCause();\n    if (cause instanceof IOException) {\n        Log.e(TAG, \"Data backup I/O failed\", cause); // inspect: disk full? permissions? corrupt tar?\n    } else throw e;\n}","preventionTips":["Keep at least 2-3x the source archive size free on the destination volume.","Verify storage permissions and that the volume is mounted read-write.","Validate source tar integrity (size/checksum) before conversion.","Log the cause chain, not just the wrapper message."],"tags":["android","backup","io","storage"],"backgroundTag":"file-write-failed","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"}