MuntashirAkon/AppManager · error · BackupException

Failed to decrypt ${Arrays.toString(dataFiles)}

Error message

Failed to decrypt ${Arrays.toString(dataFiles)}

What it means

Before extraction, restoreDirectory calls mBackupItem.decrypt(dataFiles) to decrypt encrypted backup archives; an IOException here is wrapped in this BackupException listing the files passed in. It means the backup is encrypted (crypto info present) but the archives could not be decrypted — usually a wrong password or corrupt ciphertext.

Source

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

        if (!dataSourceFile.exists()) {
            if (dataDirectoryInfo.isExternal() && !dataDirectoryInfo.isMounted) {
                if (!Utils.isRoboUnitTest()) {
                    throw new BackupException("External directory containing " + dataSource + " is not mounted.");
                } // else Skip checking for mounted partition for robolectric tests
            }
            if (!dataSourceFile.mkdirs()) {
                throw new BackupException("Could not create directory " + dataSourceFile);
            }
            if (!dataDirectoryInfo.isExternal()) {
                // Restore UID, GID
                dataSourceFile.setUidGid(uidGidPair);
            }
        }
        // Decrypt data
        try {
            dataFiles = mBackupItem.decrypt(dataFiles);
        } catch (IOException e) {
            throw new BackupException("Failed to decrypt " + Arrays.toString(dataFiles), e);
        }
        // Extract data to the data directory
        try {
            String publicSourceDir = new File(Objects.requireNonNull(mPackageInfo.applicationInfo).publicSourceDir).getParent();
            TarUtils.extract(mBackupInfo.tarType, dataFiles, dataSourceFile, null, BackupUtils
                    .getExcludeDirs(!mRequestedFlags.backupCache(), null), publicSourceDir);
        } catch (Throwable th) {
            throw new BackupException("Failed to restore data files for index " + index + ".", th);
        }
        // Restore UID and GID
        if (!Runner.runCommand(String.format(Locale.ROOT, "chown -R %d:%d \"%s\"", uidGidPair.uid, uidGidPair.gid, dataSourceFile.getFilePath())).isSuccessful()) {
            if (!Utils.isRoboUnitTest()) {
                throw new BackupException("Failed to restore ownership info for index " + index + ".");
            } // else Don't care about permissions
        }
        // Restore context
        if (!dataDirectoryInfo.isExternal()) {
            Runner.runCommand(new String[]{"restorecon", "-R", dataSourceFile.getFilePath()});

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Re-enter the correct encryption password/key used when the backup was created.
  2. Check the password for trailing whitespace or encoding issues; retype it.
  3. Re-copy the encrypted archives and the .crypto metadata from the original backup source.
  4. Restore a non-encrypted backup, or re-create the backup with a known password.
  5. Inspect the wrapped IOException message to confirm it is a decryption (bad padding/MAC) failure vs. a file-read failure.

Example fix

// before: restore with wrong password
options.setPassword(wrongPass);
new RestoreOp(...).runRestore(); // BackupException: failed to decrypt
// after: prompt until correct
while (true) {
    options.setPassword(promptPassword());
    try { runRestore(); break; }
    catch (BackupException e) { if (!e.getMessage().contains("decrypt")) throw e; }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure credentials are present and non-blank before encrypted restore
if (options.isEncrypted() && (options.getPassword() == null || options.getPassword().trim().isEmpty()))
    throw new IllegalStateException("Password required for encrypted backup");

Type guard

boolean hasDecryptionCredentials(RestoreOptions o) { return !o.isEncrypted() || (o.getPassword() != null && !o.getPassword().isEmpty()); }

Try / catch

try { runRestore(); } catch (BackupException e) {
    if (e.getMessage().contains("Failed to decrypt")) {
        if (e.getCause() instanceof IOException) promptForPasswordAgain();
    } else throw e;
}

Prevention

When it happens

Trigger: Wrong decryption password/key supplied in the restore options; backup encrypted with an algorithm/key that doesn't match the provided credentials; the encrypted files were corrupted or truncated; crypto metadata (backup.crypto) missing or tampered with while files remain encrypted.

Common situations: User forgets the password chosen at backup time; copy-pasting password with trailing whitespace; backups decrypted on another device where the key file wasn't carried over; partially synced encrypted archives.

Related errors


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