MuntashirAkon/AppManager · error · IOException

Unsupported file in AB: " + filename

Error message

Unsupported file in AB: " + filename

What it means

IOException thrown when a TAR entry from the Android backup stream, after zip-slip checks, does not fall under the expected apps/{packageName}/ prefix (relativeDirInAb). The extractor only supports entries belonging to the package being restored; anything else is rejected.

Solutions

  1. Ensure the package name used to configure the extractor matches the package inside the archive
  2. Restore each package from its own backup file rather than a multi-app archive
  3. Inspect entry names in the .ab (converted to TAR) to confirm the apps/<pkg>/ layout
  4. Regenerate the backup so entries live under the expected relative directory

Example fix

// before
AndroidBackupExtractor ex = new AndroidBackupExtractor(abFile, destDir, "com.example.other", false);
ex.extract();
// after (match package to archive contents)
String pkgInArchive = detectPackageName(abFile); // first apps/ segment
if (!pkgInArchive.equals("com.example.other")) {
    throw new IOException("Archive holds " + pkgInArchive + ", not the requested package");
}
AndroidBackupExtractor ex = new AndroidBackupExtractor(abFile, destDir, pkgInArchive, false);
ex.extract();
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm archive package matches expected before extraction
String pkg = detectFirstAppsSegment(abFile);
if (!expectedPkg.equals(pkg)) throw new IOException("Package mismatch: " + pkg);

Try / catch

try {
    extractor.extract();
} catch (IOException e) {
    if (e.getMessage().startsWith("Unsupported file in AB")) {
        Log.e(TAG, "Archive layout does not match expected package", e);
    } else throw e;
}

Prevention

When it happens

Trigger: An .ab archive whose entry paths are outside apps/<packageName>/, e.g. entries for a different package, absolute-style paths, or a mismatch between the package name the extractor was created with and the package actually contained in the archive.

Common situations: Restoring a backup of one package into another's restore session; hand-assembled or tool-generated .ab files with inconsistent directory layout; adb backup that included multiple apps but a single-app extractor is used.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/68e12527cca4eec5. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/backup/adb/AndroidBackupExtractor.java:81

        mFilesToBeDeleted.add(tarFile);
        Path dest = temporaryDir.createNewDirectory(abFilename);
        mFilesToBeDeleted.add(dest);
        toTar(abFile, tarFile, null);
        try (InputStream fis = tarFile.openInputStream();
             TarArchiveInputStream tis = new TarArchiveInputStream(fis)) {
            String realDestPath = dest.getRealFilePath();
            int relDirSize = relativeDirInAb.length();
            TarArchiveEntry entry;
            while ((entry = tis.getNextTarEntry()) != null) {
                String filename = Paths.normalize(entry.getName());
                // Early zip slip vulnerability check to avoid creating any files at all
                if (filename == null || filename.startsWith("../")) {
                    throw new IOException("Zip slip vulnerability detected!" +
                            "\nExpected dest: " + new File(realDestPath, entry.getName()) +
                            "\nActual path: " + (filename != null ? new File(realDestPath, filename) : realDestPath));
                }
                if (!filename.startsWith(relativeDirInAb)) {
                    throw new IOException("Unsupported file in AB: " + filename);
                }
                // Remove apps/{packageName}/ part
                filename = filename.substring(relDirSize);
                Path file;
                if (entry.isDirectory()) {
                    file = dest.createDirectoriesIfRequired(filename);
                } else file = dest.createNewArbitraryFile(filename, null);
                // Check if the given entry is a link.
                if (entry.isSymbolicLink() && file.getFilePath() != null) {
                    String linkName = entry.getLinkName();
                    file.delete();
                    file.createNewSymbolicLink(linkName);
                } else {
                    // Zip slip vulnerability might still be present
                    String realFilePath = file.getRealFilePath();
                    if (realDestPath != null && realFilePath != null && !realFilePath.startsWith(realDestPath)) {
                        throw new IOException("Zip slip vulnerability detected!" +
                                "\nExpected dest: " + new File(realDestPath, entry.getName()) +

View on GitHub (pinned to 0152f468fc)