MuntashirAkon/AppManager · error · BackupException

Failed to restore rules file.

Error message

Failed to restore rules file.

What it means

restoreRules throws this when RulesImporter.applyRules() raises an IOException after the rules file was successfully decrypted. The file contents are readable/valid enough to decrypt, but parsing or applying the rules to the package database failed at the I/O level.

Solutions

  1. Check device storage and that the AppManager data/rules directory is writable.
  2. Update AppManager so the current RuleType set understands the backup's rules format.
  3. Recreate the backup from the source device with the current app version, then restore again.
  4. Verify the target package and user ID (mUserId) exist on this device before restoring.

Example fix

// before: old backup format fails silently into IOException
importer.applyRules(true);
// after: regenerate the backup with the installed version, or upgrade AppManager first
// adb shell pm list packages --user <mUserId>  # confirm user/package exists, then retry restore
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: package and user exist, rules dir writable
boolean userExists = userManager.getUserIds().length > mUserId;
boolean writable = new File(rulesDir).canWrite();

Try / catch

try {
    restoreOp.runRestore();
} catch (BackupException e) {
    if ("Failed to restore rules file.".equals(e.getMessage())) {
        // check storage space, AppManager version, and target user
    }
}

Prevention

When it happens

Trigger: runRestore on a backup whose decrypted rules file cannot be parsed into paths (addRulesFromPath) or applied (applyRules(true)) due to unreadable app-private storage, unsupported rules content for the current RuleType set, or an I/O failure while writing imported rules.

Common situations: Restoring an old backup whose rules format is no longer understood, insufficient storage or SELinux denials preventing writes to the rules directory, or importing rules for a package/user (mUserId) that no longer exists.

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/3bd4d6175c05af75. Report an issue: GitHub.

Appendix: source

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

            if (!checksum.equals(mChecksum.get(rulesFile.getName()))) {
                throw new BackupException("Couldn't verify permission file." +
                        "\nFile: " + rulesFile +
                        "\nFound: " + checksum +
                        "\nRequired: " + mChecksum.get(rulesFile.getName()));
            }
        }
        // Decrypt rules file
        try {
            rulesFile = mBackupItem.decrypt(new Path[]{rulesFile})[0];
        } catch (IOException | IndexOutOfBoundsException e) {
            throw new BackupException("Failed to decrypt " + rulesFile.getName(), e);
        }
        try (RulesImporter importer = new RulesImporter(Arrays.asList(RuleType.values()), new int[]{mUserId})) {
            importer.addRulesFromPath(rulesFile);
            importer.setPackagesToImport(Collections.singletonList(mPackageName));
            importer.applyRules(true);
        } catch (IOException e) {
            throw new BackupException("Failed to restore rules file.", e);
        }
    }

    private void deleteFiles(@NonNull Path[] files) {
        for (Path file : files) {
            file.delete();
        }
    }
}

View on GitHub (pinned to 0152f468fc)