MuntashirAkon/AppManager · error · BackupException

Failed to access properties of the KeyStore folder.

Error message

Failed to access properties of the KeyStore folder.

What it means

Before extracting keystore files into /data/misc/keystore, restoreKeyStore reads that folder's UID/GID and permission mode so ownership can be restored after extraction. This error means querying those properties threw an ErrnoException — the keystore directory could not be stat'd. Without them, AppManager cannot safely restore ownership, so it aborts.

Solutions

  1. Ensure AppManager is running with root (or the required privileged mode) before restoring keystore.
  2. Verify /data/misc/keystore (per mUserId) exists; create or boot the device so the directory is initialized.
  3. Check SELinux denials in logcat and use a mode that permits stat on the keystore folder.
  4. Abort keystore restore on non-standard ROMs where the keystore path differs.

Example fix

// before
uidGidPair = Objects.requireNonNull(keyStorePath.getFile()).getUidGid();
mode = keyStorePath.getFile().getMode();
// after
File ksFile = keyStorePath.getFile();
if (ksFile == null || !ksFile.exists()) {
    throw new BackupException("KeyStore folder does not exist for user " + mUserId);
}
uidGidPair = ksFile.getUidGid();
mode = ksFile.getMode();
Defensive patterns

Strategy: try-catch

Validate before calling

File ks = keyStorePath.getFile();
if (ks == null || !ks.exists()) throw new ErrnoException("keystore-path", OsConstants.ENOENT);
if (!isPrivileged()) throw new SecurityException("Root required for keystore restore");

Type guard

boolean canStatKeystore(Path p) { try { return p.getFile() != null && p.getFile().exists(); } catch (Exception e) { return false; } }

Try / catch

try { uidGidPair = ksFile.getUidGid(); mode = ksFile.getMode(); } catch (ErrnoException e) { throw new BackupException("Failed to access properties of the KeyStore folder.", e); }

Prevention

When it happens

Trigger: keyStorePath.getFile().getUidGid() or getMode() throws ErrnoException: /data/misc/keystore does not exist for mUserId, or the process lacks root/permission to stat it.

Common situations: Running without root/adb privileges; non-standard ROMs with a different keystore path; multi-user setups where the per-user keystore directory is absent; SELinux denials on stat.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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

Appendix: source

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

                }
            }
        }
        // Decrypt sources
        try {
            keyStoreFiles = mBackupItem.decrypt(keyStoreFiles);
        } catch (IOException e) {
            throw new BackupException("Failed to decrypt " + Arrays.toString(keyStoreFiles), e);
        }
        // Restore KeyStore files to the /data/misc/keystore folder
        Path keyStorePath = KeyStoreUtils.getKeyStorePath(mUserId);
        // Note down UID/GID
        UidGidPair uidGidPair;
        int mode;
        try {
            uidGidPair = Objects.requireNonNull(keyStorePath.getFile()).getUidGid();
            mode = keyStorePath.getFile().getMode();
        } catch (ErrnoException e) {
            throw new BackupException("Failed to access properties of the KeyStore folder.", e);
        }
        try {
            TarUtils.extract(mBackupInfo.tarType, keyStoreFiles, keyStorePath, null, null, null);
            // Restore folder permission
            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

View on GitHub (pinned to 0152f468fc)