MuntashirAkon/AppManager · error · BackupException
Couldn't decompress
Error message
Couldn't decompress
What it means
While streaming the decompressed APK from the source archive to a staging file, any IOException is wrapped as "Couldn't decompress <apkName>". It means the source APK archive could not be read/decompressed or the staged APK file could not be written.
Solutions
- Verify the source backup archive integrity (try decompressing it manually; check gzip/bzip2 test passes).
- Re-transfer or re-create the source backup if the archive is truncated or corrupt.
- Check free space and write permissions in the staging/temp directory.
- Confirm the APK file referenced by mSourceMetadata.apkName still exists in the source backup.
Example fix
// before
// blindly converting possibly corrupted source
convert();
// after
if (!DigestUtils.matchesHexDigest(archivePath, sourceMetadata.checksums.get("apk"))) {
throw new IOException("Source APK archive corrupted; re-transfer the backup");
}
convert(); Defensive patterns
Strategy: validation
Validate before calling
// Verify source archive integrity before conversion
if (!DigestUtils.getHexDigest(checksumAlgo, sourceApkArchive)
.equals(sourceMetadata.checksums.get("apk"))) {
throw new IOException("Source APK archive checksum mismatch — re-transfer backup");
} Try / catch
try {
converter.convert();
} catch (BackupException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Couldn't decompress")) {
verifySourceIntegrity(); // run gzip/bzip2 -t and tar listing; re-transfer if corrupt
}
} Prevention
- Always verify source backup checksums before converting.
- Avoid interrupted transfers: re-copy from a stable source if the archive came from PC/cloud.
- Ensure ample free space in the staging directory before extraction.
When it happens
Trigger: IoUtils.copy(is, fos) or closing the streams throws IOException: the source tar/compressed stream is truncated or corrupted (bad gzip/bzip2 block), the source file is unreadable, or writing to the staging directory fails (space/permissions).
Common situations: Source backup files partially copied from a PC or cloud, yielding corrupt .gz/.bz2 archives; disk full while staging the APK; SD card removed mid-operation; source file renamed/deleted after metadata was read.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- broken archive, entry with negative size
- Corrupted input, " + name + " value negative
- Error detected parsing the header
- Paxheader value size
- ADB command did not produce
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/7e531da09ace5c1f.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/io/github/muntashirakon/AppManager/backup/convert/TBConverter.java:209
BufferedInputStream bis = new BufferedInputStream(pis)) {
CompressorInputStream is;
if (TAR_GZIP.equals(mSourceMetadata.tarType)) {
is = new GzipCompressorInputStream(bis, true);
} else if (TAR_BZIP2.equals(mSourceMetadata.tarType)) {
is = new BZip2CompressorInputStream(bis, true);
} else {
baseApkFile.requireParent().delete();
throw new BackupException("Invalid source compression type: " + mSourceMetadata.tarType);
}
try (OutputStream fos = baseApkFile.openOutputStream()) {
// The whole file is the APK
IoUtils.copy(is, fos);
} finally {
is.close();
}
} catch (IOException e) {
baseApkFile.requireParent().delete();
throw new BackupException("Couldn't decompress " + mSourceMetadata.apkName, e);
}
// Get certificate checksums
try {
String[] checksums = ConvertUtils.getChecksumsFromApk(baseApkFile, mDestMetadata.info.checksumAlgo);
for (int i = 0; i < checksums.length; ++i) {
mChecksum.add(CERT_PREFIX + i, checksums[i]);
}
} catch (Exception ignore) {
}
// Backup APK file
String sourceBackupFilePrefix = BackupUtils.getSourceFilePrefix(getExt(mDestMetadata.info.tarType));
Path[] sourceFiles;
try {
sourceFiles = TarUtils.create(mDestMetadata.info.tarType, baseApkFile, mBackupItem.getUnencryptedBackupPath(), sourceBackupFilePrefix,
/* language=regexp */new String[]{".*\\.apk"}, null, null, false)
.toArray(new Path[0]);
} catch (Throwable th) {
throw new BackupException("APK files backup is requested but no APK files have been backed up.", th);View on GitHub (pinned to 0152f468fc)