MuntashirAkon/AppManager · error · FileNotFoundException

does not exist.

Error message

${ksUri} does not exist.

What it means

KeyStoreUtils.listAliases opens the keystore file through a ContentResolver stream. When openInputStream returns null (the provider cannot open the URI) it throws FileNotFoundException naming the URI: "<ksUri> does not exist." The library throws this because keystore loading requires a readable input stream.

Solutions

  1. Re-select the keystore file so a fresh, valid document URI is used.
  2. Verify the file exists and is readable at the given path for file:// URIs (File.exists(), canRead()).
  3. Take a persistable URI permission (takePersistableUriPermission) after SAF selection so the URI stays openable.
  4. Check the URI scheme/provider is available (e.g. external storage mounted).

Example fix

// before
Uri ksUri = data.getData();
List<String> aliases = KeyStoreUtils.listAliases(context, ksUri, ksType, ksPass);
// after
Uri ksUri = data.getData();
final int flags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION
        | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
context.getContentResolver().takePersistableUriPermission(ksUri, flags);
try (InputStream test = context.getContentResolver().openInputStream(ksUri)) {
    if (test == null) throw new FileNotFoundException(ksUri + " does not exist.");
}
List<String> aliases = KeyStoreUtils.listAliases(context, ksUri, ksType, ksPass);
Defensive patterns

Strategy: validation

Validate before calling

// verify the URI is openable before calling listAliases
try (InputStream probe = context.getContentResolver().openInputStream(ksUri)) {
    if (probe == null) {
        throw new FileNotFoundException("Keystore URI unreadable: " + ksUri);
    }
}

Type guard

boolean isReadableUri(Context ctx, Uri uri) {
    if (uri == null) return false;
    try (InputStream is = ctx.getContentResolver().openInputStream(uri)) {
        return is != null;
    } catch (IOException | SecurityException e) {
        return false;
    }
}

Try / catch

// try
try {
    List<String> aliases = KeyStoreUtils.listAliases(context, ksUri, ksType, ksPass);
} catch (FileNotFoundException e) {
    // URI unopenable: re-launch SAF picker for the keystore file
    launchKeyStorePicker();
}

Prevention

When it happens

Trigger: Calling listAliases(context, ksUri, ksType, ksPass) with a URI the ContentResolver cannot open: file deleted/moved, no read permission, or an invalid/unresolvable content:// or file:// URI.

Common situations: User picked a keystore file via SAF but later moved/deleted it; document URI from a removed external-storage provider; missing persistable permission on the SAF grant.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreUtils.java:111

    }

    public static final String KEY_STORE_TYPE_JKS = "JKS";
    public static final String KEY_STORE_TYPE_PKCS12 = "PKCS12";
    public static final String KEY_STORE_TYPE_BKS = "BKS";

    private static final String[] TYPES = {KEY_STORE_TYPE_JKS, KEY_STORE_TYPE_PKCS12, KEY_STORE_TYPE_BKS};

    @NonNull
    public static ArrayList<String> listAliases(@NonNull Context context,
                                                @NonNull Uri ksUri,
                                                @KeyType int ksType,
                                                @Nullable char[] ksPass)
            throws IOException, GeneralSecurityException {
        String keyType = TYPES[ksType];
        Log.d(TAG, "Loading keystore %s", keyType);
        final KeyStore ks = KeyStore.getInstance(keyType, getKeyStoreProvider(keyType));
        try (InputStream is = context.getContentResolver().openInputStream(ksUri)) {
            if (is == null) throw new FileNotFoundException(ksUri + " does not exist.");
            ks.load(is, ksPass);
        }
        return Collections.list(ks.aliases());
    }

    @NonNull
    public static KeyPair getKeyPair(@NonNull Context context, @NonNull Uri ksUri, @KeyType int ksType,
                                     @Nullable String ksAlias, @Nullable char[] ksPass,
                                     @Nullable char[] aliasPass)
            throws GeneralSecurityException, IOException {
        String keyType = TYPES[ksType];
        Log.d(TAG, "Loading keystore %s", keyType);
        final KeyStore ks = KeyStore.getInstance(keyType, getKeyStoreProvider(keyType));
        try (InputStream is = context.getContentResolver().openInputStream(ksUri)) {
            if (is == null) throw new FileNotFoundException(ksUri + " does not exist.");
            ks.load(is, ksPass);
        }
        if (TextUtils.isEmpty(ksAlias)) {

View on GitHub (pinned to 0152f468fc)