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
- Ensure the package name used to configure the extractor matches the package inside the archive
- Restore each package from its own backup file rather than a multi-app archive
- Inspect entry names in the .ab (converted to TAR) to confirm the apps/<pkg>/ layout
- 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
- Match the extractor's package argument to the archive contents
- Restore single-app backups individually
- Use the same tool version for backup and restore
- Inspect entry paths after converting .ab to TAR when debugging
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
- APK files backup is requested but no APK files have been…
- APK files backup is requested but no APK files have been…
- APK files backup is requested but no source directory has…
- Backup failed for
- Backup failed for
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)