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

  1. Verify the source backup archive integrity (try decompressing it manually; check gzip/bzip2 test passes).
  2. Re-transfer or re-create the source backup if the archive is truncated or corrupt.
  3. Check free space and write permissions in the staging/temp directory.
  4. 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

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


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)