MuntashirAkon/AppManager · error · BackupException

Failed to rename KeyStore files

Error message

Failed to rename KeyStore files

What it means

After extracting the KeyStore files, restoreKeyStore renames each placeholder-named file (KEYSTORE_PLACEHOLDER in the name) to the app's real UID. This error is thrown when any rename or the per-file chown/chmod (mode 0600) throws IOException or ErrnoException. The KeyStore files are extracted but remain misnamed, so the restore is aborted.

Source

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

            Paths.chown(keyStorePath, uidGidPair.uid, uidGidPair.gid);
            //noinspection OctalInteger
            Paths.chmod(keyStorePath, mode & 0777);
        } catch (Throwable th) {
            throw new BackupException("Failed to restore the KeyStore files.", th);
        }
        // Rename files
        List<String> keyStoreFileNames = KeyStoreUtils.getKeyStoreFiles(KEYSTORE_PLACEHOLDER, mUserId);
        for (String keyStoreFileName : keyStoreFileNames) {
            try {
                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 + ".");

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Run with root privileges so chown/chmod on the renamed KeyStore files succeed.
  2. Verify the backup's KeyStore files use the current KEYSTORE_PLACEHOLDER naming convention (same App Manager version that created them).
  3. Check for pre-existing files at the target names (UID collision, e.g. sharedUserId apps) and remove conflicts before restore.
  4. Read the wrapped exception to distinguish rename failure from permission failure.
  5. Re-create the backup with the installed App Manager version and restore again.

Example fix

// before
catch (IOException | ErrnoException e) { throw new BackupException("Failed to rename KeyStore files", e); }
// after: ensure target does not already exist before findFile/rename
Path target = keyStorePath.resolve(newFilename);
if (target.exists()) { // remove stale target first
    Paths.delete(target);
}
// then perform the rename as before
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check: no files already occupy the placeholder-renamed targets
for (String name : expectedRenamedNames) {
    if (keyStorePath.resolve(name).exists()) throw new IllegalStateException("Target exists: " + name);
}

Type guard

boolean renameTargetsFree(Path dir, List<String> targets) { return targets.stream().noneMatch(t -> dir.resolve(t).exists()); }

Try / catch

try { runRestore(); } catch (BackupException e) {
    if (e.getMessage().contains("rename KeyStore")) {
        Throwable c = e.getCause();
        if (c instanceof ErrnoException) logErrno(((ErrnoException) c).errno);
    } else throw e;
}

Prevention

When it happens

Trigger: keyStorePath.findFile(newFilename) returns null / throws because the expected placeholder file is absent; rename(2) fails (file locked, name collision); Paths.chown/chmod on targetFile throws ErrnoException due to missing root or SELinux denial.

Common situations: Backup created by a different App Manager version using a different placeholder naming scheme; two apps sharing a UID causing filename collisions; restoring without root so chmod 0600/chown fail; files altered between checksum verification and rename.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


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