{"record":{"id":"251d34e42b66c203","repo":"MuntashirAkon/AppManager","slug":"could-not-resolve-uri","errorCode":null,"errorMessage":"Could not resolve Uri: ","messagePattern":"Could not resolve Uri: ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/io/PathImpl.java","lineNumber":1220,"sourceCode":"    @NonNull\n    public OutputStream openOutputStream(boolean append) throws IOException {\n        DocumentFile documentFile = resolveFileOrNull(this.documentFile);\n        if (documentFile == null) {\n            throw new IOException(this.documentFile.getUri() + \" is a directory\");\n        }\n        if (documentFile instanceof ExtendedRawDocumentFile) {\n            try {\n                return Objects.requireNonNull(getFile()).newOutputStream(append);\n            } catch (IOException e) {\n                throw new IOException(\"Could not open file for writing: \" + documentFile.getUri(), e);\n            }\n        } else if (documentFile instanceof VirtualDocumentFile) {\n            return ((VirtualDocumentFile) documentFile).openOutputStream(append);\n        }\n        String mode = \"w\" + (append ? \"a\" : \"t\");\n        OutputStream os = context.getContentResolver().openOutputStream(documentFile.getUri(), mode);\n        if (os == null) {\n            throw new IOException(\"Could not resolve Uri: \" + documentFile.getUri());\n        }\n        return os;\n    }\n\n    @NonNull\n    public InputStream openInputStream() throws IOException {\n        DocumentFile documentFile = resolveFileOrNull(this.documentFile);\n        if (documentFile == null) {\n            throw new IOException(this.documentFile.getUri() + \" is a directory\");\n        }\n        if (documentFile instanceof ExtendedRawDocumentFile) {\n            try {\n                return Objects.requireNonNull(getFile()).newInputStream();\n            } catch (IOException e) {\n                throw new IOException(\"Could not open file for reading: \" + documentFile.getUri(), e);\n            }\n        } else if (documentFile instanceof VirtualDocumentFile) {\n            return ((VirtualDocumentFile) documentFile).openInputStream();","sourceCodeStart":1202,"sourceCodeEnd":1238,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/io/PathImpl.java#L1202-L1238","documentation":"As the final fallback, openOutputStream() uses context.getContentResolver().openOutputStream(uri, mode) with mode \"w\" or \"wa\"; ContentResolver returns null when it cannot open a stream (unknown/unresolvable provider, bad URI, or provider denial), so the method throws IOException(\"Could not resolve Uri: <uri>\"). Unlike a thrown exception from the provider, a null return means the URI could not be turned into a stream at all.","triggerScenarios":"Calling openOutputStream on a Path whose documentFile is neither ExtendedRawDocumentFile nor VirtualDocumentFile, and ContentResolver.openOutputStream returns null — invalid or revoked document URI, unsupported provider, or permission not granted/persisted.","commonSituations":"Using a document URI after the SAF permission grant was revoked or the device rebooted without takePersistableUriPermission, or a Uri from a different app/provider that no longer exists.","solutions":["Verify the URI is valid and permissions are still held (check persisted URI permissions)","Re-acquire access via the SAF picker and takePersistableUriPermission(MODE_READ|WRITE)","Catch the IOException and re-prompt the user to reselect the location"],"exampleFix":"// before\nOutputStream os = path.openOutputStream();\n// after\ntry {\n    OutputStream os = path.openOutputStream();\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Could not resolve Uri\")) {\n        // re-request SAF access\n    }\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"// ensure persisted SAF permission\nfor (UriPermissions p : context.getContentResolver().getPersistedUriPermissions()) {\n    if (p.getUri().equals(treeUri) && p.isWritePermission()) return;\n}\nthrow new IOException(\"No persisted write permission for \" + treeUri);","typeGuard":null,"tryCatchPattern":"try {\n    OutputStream os = path.openOutputStream(append);\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Could not resolve Uri\")) {\n        // re-acquire access via SAF picker\n    } else throw e;\n}","preventionTips":["Call takePersistableUriPermission after every SAF result","Handle FLAG_GRANT_PERSISTABLE across reboots","Validate the URI still exists before opening streams"],"tags":["io","android","saf","uri"],"backgroundTag":"file-open-failed","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}