{"record":{"id":"c549b9cbe5e28a74","repo":"MuntashirAkon/AppManager","slug":"failed-to-rename-keystore-files","errorCode":null,"errorMessage":"Failed to rename KeyStore files","messagePattern":"Failed to rename KeyStore files","errorType":"exception","errorClass":"BackupException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java","lineNumber":474,"sourceCode":"            Paths.chown(keyStorePath, uidGidPair.uid, uidGidPair.gid);\n            //noinspection OctalInteger\n            Paths.chmod(keyStorePath, mode & 0777);\n        } catch (Throwable th) {\n            throw new BackupException(\"Failed to restore the KeyStore files.\", th);\n        }\n        // Rename files\n        List<String> keyStoreFileNames = KeyStoreUtils.getKeyStoreFiles(KEYSTORE_PLACEHOLDER, mUserId);\n        for (String keyStoreFileName : keyStoreFileNames) {\n            try {\n                String newFilename = Utils.replaceOnce(keyStoreFileName, String.valueOf(KEYSTORE_PLACEHOLDER), String.valueOf(mUid));\n                keyStorePath.findFile(keyStoreFileName).renameTo(newFilename);\n                Path targetFile = keyStorePath.findFile(newFilename);\n                // Restore file permission\n                Paths.chown(targetFile, uidGidPair.uid, uidGidPair.gid);\n                //noinspection OctalInteger\n                Paths.chmod(targetFile, 0600);\n            } catch (IOException | ErrnoException e) {\n                throw new BackupException(\"Failed to rename KeyStore files\", e);\n            }\n        }\n        Runner.runCommand(new String[]{\"restorecon\", \"-R\", keyStorePath.getFilePath()});\n    }\n\n    private void restoreData() throws BackupException {\n        // Data restore is requested: Data restore is only possible if the app is actually\n        // installed. So, check if it's installed first.\n        if (mPackageInfo == null) {\n            throw new BackupException(\"Data restore is requested but the app isn't installed.\");\n        }\n        if (!mRequestedFlags.skipSignatureCheck()) {\n            // Verify integrity of the data backups\n            String checksum;\n            for (int i = 0; i < mBackupMetadata.dataDirs.length; ++i) {\n                Path[] dataFiles = mBackupItem.getDataFiles(i);\n                if (dataFiles.length == 0) {\n                    throw new BackupException(\"Data restore is requested but there are no data files for index \" + i + \".\");","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/backup/RestoreOp.java#L456-L492","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run with root privileges so chown/chmod on the renamed KeyStore files succeed.","Verify the backup's KeyStore files use the current KEYSTORE_PLACEHOLDER naming convention (same App Manager version that created them).","Check for pre-existing files at the target names (UID collision, e.g. sharedUserId apps) and remove conflicts before restore.","Read the wrapped exception to distinguish rename failure from permission failure.","Re-create the backup with the installed App Manager version and restore again."],"exampleFix":"// before\ncatch (IOException | ErrnoException e) { throw new BackupException(\"Failed to rename KeyStore files\", e); }\n// after: ensure target does not already exist before findFile/rename\nPath target = keyStorePath.resolve(newFilename);\nif (target.exists()) { // remove stale target first\n    Paths.delete(target);\n}\n// then perform the rename as before","handlingStrategy":"try-catch","validationCode":"// Pre-check: no files already occupy the placeholder-renamed targets\nfor (String name : expectedRenamedNames) {\n    if (keyStorePath.resolve(name).exists()) throw new IllegalStateException(\"Target exists: \" + name);\n}","typeGuard":"boolean renameTargetsFree(Path dir, List<String> targets) { return targets.stream().noneMatch(t -> dir.resolve(t).exists()); }","tryCatchPattern":"try { runRestore(); } catch (BackupException e) {\n    if (e.getMessage().contains(\"rename KeyStore\")) {\n        Throwable c = e.getCause();\n        if (c instanceof ErrnoException) logErrno(((ErrnoException) c).errno);\n    } else throw e;\n}","preventionTips":["Restore with root so chmod 0600/chown succeed.","Don't rename or pre-place files in the KeyStore staging directory.","Use matching App Manager versions for backup and restore (placeholder scheme).","Check for UID collisions from sharedUserId apps before restoring."],"tags":["android","backup","keystore","file-rename","permissions"],"backgroundTag":"file-write-failed","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}