{"record":{"id":"bebbf241786e3e13","repo":"MuntashirAkon/AppManager","slug":"ksuri-does-not-exist","errorCode":null,"errorMessage":"${ksUri} does not exist.","messagePattern":"(.+?) does not exist\\.","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreUtils.java","lineNumber":111,"sourceCode":"    }\n\n    public static final String KEY_STORE_TYPE_JKS = \"JKS\";\n    public static final String KEY_STORE_TYPE_PKCS12 = \"PKCS12\";\n    public static final String KEY_STORE_TYPE_BKS = \"BKS\";\n\n    private static final String[] TYPES = {KEY_STORE_TYPE_JKS, KEY_STORE_TYPE_PKCS12, KEY_STORE_TYPE_BKS};\n\n    @NonNull\n    public static ArrayList<String> listAliases(@NonNull Context context,\n                                                @NonNull Uri ksUri,\n                                                @KeyType int ksType,\n                                                @Nullable char[] ksPass)\n            throws IOException, GeneralSecurityException {\n        String keyType = TYPES[ksType];\n        Log.d(TAG, \"Loading keystore %s\", keyType);\n        final KeyStore ks = KeyStore.getInstance(keyType, getKeyStoreProvider(keyType));\n        try (InputStream is = context.getContentResolver().openInputStream(ksUri)) {\n            if (is == null) throw new FileNotFoundException(ksUri + \" does not exist.\");\n            ks.load(is, ksPass);\n        }\n        return Collections.list(ks.aliases());\n    }\n\n    @NonNull\n    public static KeyPair getKeyPair(@NonNull Context context, @NonNull Uri ksUri, @KeyType int ksType,\n                                     @Nullable String ksAlias, @Nullable char[] ksPass,\n                                     @Nullable char[] aliasPass)\n            throws GeneralSecurityException, IOException {\n        String keyType = TYPES[ksType];\n        Log.d(TAG, \"Loading keystore %s\", keyType);\n        final KeyStore ks = KeyStore.getInstance(keyType, getKeyStoreProvider(keyType));\n        try (InputStream is = context.getContentResolver().openInputStream(ksUri)) {\n            if (is == null) throw new FileNotFoundException(ksUri + \" does not exist.\");\n            ks.load(is, ksPass);\n        }\n        if (TextUtils.isEmpty(ksAlias)) {","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreUtils.java#L93-L129","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nUri ksUri = data.getData();\nList<String> aliases = KeyStoreUtils.listAliases(context, ksUri, ksType, ksPass);\n// after\nUri ksUri = data.getData();\nfinal int flags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION\n        | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);\ncontext.getContentResolver().takePersistableUriPermission(ksUri, flags);\ntry (InputStream test = context.getContentResolver().openInputStream(ksUri)) {\n    if (test == null) throw new FileNotFoundException(ksUri + \" does not exist.\");\n}\nList<String> aliases = KeyStoreUtils.listAliases(context, ksUri, ksType, ksPass);","handlingStrategy":"validation","validationCode":"// verify the URI is openable before calling listAliases\ntry (InputStream probe = context.getContentResolver().openInputStream(ksUri)) {\n    if (probe == null) {\n        throw new FileNotFoundException(\"Keystore URI unreadable: \" + ksUri);\n    }\n}","typeGuard":"boolean isReadableUri(Context ctx, Uri uri) {\n    if (uri == null) return false;\n    try (InputStream is = ctx.getContentResolver().openInputStream(uri)) {\n        return is != null;\n    } catch (IOException | SecurityException e) {\n        return false;\n    }\n}","tryCatchPattern":"// try\ntry {\n    List<String> aliases = KeyStoreUtils.listAliases(context, ksUri, ksType, ksPass);\n} catch (FileNotFoundException e) {\n    // URI unopenable: re-launch SAF picker for the keystore file\n    launchKeyStorePicker();\n}","preventionTips":["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."],"tags":["keystore","android","file-not-found","uri"],"backgroundTag":"file-not-found","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}