MuntashirAkon/AppManager · error · BackupException

Couldn't verify permission file.\nFile: ${rulesFile}\nFound:

Error message

Couldn't verify permission file.\nFile: ${rulesFile}\nFound: ${checksum}\nRequired: ${mChecksum.get(rulesFile.getName())}

What it means

RestoreOp.restoreRules throws this BackupException when the on-disk permission/rules file's checksum (computed with the backup's recorded algorithm) does not match the checksum stored in the backup's checksum map. It is an integrity check to detect a corrupted or tampered rules file during restore, and can be bypassed only with the skipSignatureCheck flag.

Source

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

        // Apply rules
        if (!mIsInstalled) {
            throw new BackupException("Rules restore is requested but the app isn't installed.");
        }
        Path rulesFile;
        try {
            rulesFile = mBackupItem.getRulesFile();
        } catch (IOException e) {
            if (mBackupMetadata.hasRules) {
                throw new BackupException("Rules file is missing.", e);
            } else {
                // There are no rules, just skip
                return;
            }
        }
        if (!mRequestedFlags.skipSignatureCheck()) {
            String checksum = DigestUtils.getHexDigest(mBackupInfo.checksumAlgo, rulesFile);
            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);
        }

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Recopy or re-download the backup from a trusted source so the rules file matches the recorded checksum.
  2. Take a fresh backup of the app so a new rules file and matching checksum are generated.
  3. If you accept the risk, re-run restore with the skip-signature-check flag so the checksum comparison is skipped.
  4. Verify the checksum algorithm support: if the backup came from an older version, ensure DigestUtils supports the recorded checksumAlgo.

Example fix

// before
am --backup-restore restore <backup>
// after (skip integrity check deliberately)
am --backup-restore restore <backup> --skip-signature-check
Defensive patterns

Strategy: validation

Validate before calling

// Verify the rules file digest before starting restore
String algo = backupInfo.checksumAlgo;
String actual = DigestUtils.getHexDigest(algo, rulesFile);
String expected = checksumMap.get(new File(rulesFile).getName());
boolean ok = actual != null && actual.equals(expected);

Try / catch

try {
    restoreOp.runRestore();
} catch (BackupException e) {
    if (e.getMessage().startsWith("Couldn't verify permission file.")) {
        // prompt user to re-copy backup or re-run with skipSignatureCheck
    }
}

Prevention

When it happens

Trigger: Calling runRestore with backupRules enabled while the rules file (e.g. permissions.xml or rules JSON) was modified after backup, partially downloaded/copied, or re-encoded with different formatting/line endings so the digest differs from mChecksum.

Common situations: Backups transferred over unreliable channels (MTP, cloud sync truncating files), files edited manually on device, restoring a backup taken by a different AppManager version that serialized rules differently, or a storage corruption on the backup media.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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