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
- Re-select the keystore file so a fresh, valid document URI is used.
- Verify the file exists and is readable at the given path for file:// URIs (File.exists(), canRead()).
- Take a persistable URI permission (takePersistableUriPermission) after SAF selection so the URI stays openable.
- 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
- Take persistable URI permissions when the user selects a keystore via SAF.
- Check file existence/readability for file:// URIs before use.
- Re-resolve URIs stored long-term — providers can revoke or move documents.
- Catch FileNotFoundException at the picker/UI layer and prompt for re-selection.
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
- does not exist.
- Alias exists.
- Alias app_manager does not exist in KeyStore.
- Cannot find
- Checksums for master key did not match.
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)