MuntashirAkon/AppManager · error · BackupException

Data restore is requested but the app isn't installed.

Error message

Data restore is requested but the app isn't installed.

What it means

restoreData requires the target app to actually be installed because data can only be restored into an existing package. If mPackageInfo is null (the package was not found / not installed for this user), this BackupException is thrown before any data work begins. It is an explicit precondition check, not an I/O failure.

Solutions

  1. Install the app (APK from the backup or store) before running the data restore.
  2. Ensure the restore targets the correct userId where the app is installed (or install for that user).
  3. If only app data exists in the backup, restore the APK part first or switch to a full (APK+data) restore.
  4. Verify the package name spelling matches the installed package.

Example fix

// before: attempting data-only restore for uninstalled app
restoreOp.runRestore(); // throws BackupException
// after: guard in caller
if (restoreOp.isDataRestoreRequested() && getInstalledPackageInfo(pkg, userId) == null) {
    installApkFromBackup(pkg); // install first
}
restoreOp.runRestore();
Defensive patterns

Strategy: validation

Validate before calling

PackageInfo pi = getPackageManager().getPackageInfoAsUser(pkg, 0, userId);
if (pi == null) throw new IllegalStateException("App must be installed before data restore: " + pkg);

Type guard

boolean isInstalled(PackageInfo pi) { return pi != null && pi.applicationInfo != null; }

Try / catch

try { runRestore(); } catch (BackupException e) {
    if (e.getMessage().contains("isn't installed")) {
        installApkFromBackupThenRetry(pkg);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling the restore flow with data restore requested for a package that is not installed on the device/user; the package was uninstalled (even with keepData) before running restore; wrong userId so PackageInstaller cannot see the installed package.

Common situations: Restoring only-data backup onto a fresh device without first installing the APK; restoring for a work-profile user where the app is installed only in the main user; typo'd or stale package name in a scripted restore.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java:484

                String newFilename = Utils.replaceOnce(keyStoreFileName, String.valueOf(KEYSTORE_PLACEHOLDER), String.valueOf(mUid));
                keyStorePath.findFile(keyStoreFileName).renameTo(newFilename);
                Path targetFile = keyStorePath.findFile(newFilename);
                // Restore file permission
                Paths.chown(targetFile, uidGidPair.uid, uidGidPair.gid);
                //noinspection OctalInteger
                Paths.chmod(targetFile, 0600);
            } catch (IOException | ErrnoException e) {
                throw new BackupException("Failed to rename KeyStore files", e);
            }
        }
        Runner.runCommand(new String[]{"restorecon", "-R", keyStorePath.getFilePath()});
    }

    private void restoreData() throws BackupException {
        // Data restore is requested: Data restore is only possible if the app is actually
        // installed. So, check if it's installed first.
        if (mPackageInfo == null) {
            throw new BackupException("Data restore is requested but the app isn't installed.");
        }
        if (!mRequestedFlags.skipSignatureCheck()) {
            // Verify integrity of the data backups
            String checksum;
            for (int i = 0; i < mBackupMetadata.dataDirs.length; ++i) {
                Path[] dataFiles = mBackupItem.getDataFiles(i);
                if (dataFiles.length == 0) {
                    throw new BackupException("Data restore is requested but there are no data files for index " + i + ".");
                }
                for (Path file : dataFiles) {
                    checksum = DigestUtils.getHexDigest(mBackupInfo.checksumAlgo, file);
                    if (!checksum.equals(mChecksum.get(file.getName()))) {
                        throw new BackupException("Data file verification failed for index " + i + "." +
                                "\nFile: " + file +
                                "\nFound: " + checksum +
                                "\nRequired: " + mChecksum.get(file.getName()));
                    }
                }

View on GitHub (pinned to 0152f468fc)