MuntashirAkon/AppManager · error · IOException

Could not resolve Uri:

Error message

Could not resolve Uri: 

What it means

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.

Source

Thrown at app/src/main/java/io/github/muntashirakon/io/PathImpl.java:1220

    @NonNull
    public OutputStream openOutputStream(boolean append) throws IOException {
        DocumentFile documentFile = resolveFileOrNull(this.documentFile);
        if (documentFile == null) {
            throw new IOException(this.documentFile.getUri() + " is a directory");
        }
        if (documentFile instanceof ExtendedRawDocumentFile) {
            try {
                return Objects.requireNonNull(getFile()).newOutputStream(append);
            } catch (IOException e) {
                throw new IOException("Could not open file for writing: " + documentFile.getUri(), e);
            }
        } else if (documentFile instanceof VirtualDocumentFile) {
            return ((VirtualDocumentFile) documentFile).openOutputStream(append);
        }
        String mode = "w" + (append ? "a" : "t");
        OutputStream os = context.getContentResolver().openOutputStream(documentFile.getUri(), mode);
        if (os == null) {
            throw new IOException("Could not resolve Uri: " + documentFile.getUri());
        }
        return os;
    }

    @NonNull
    public InputStream openInputStream() throws IOException {
        DocumentFile documentFile = resolveFileOrNull(this.documentFile);
        if (documentFile == null) {
            throw new IOException(this.documentFile.getUri() + " is a directory");
        }
        if (documentFile instanceof ExtendedRawDocumentFile) {
            try {
                return Objects.requireNonNull(getFile()).newInputStream();
            } catch (IOException e) {
                throw new IOException("Could not open file for reading: " + documentFile.getUri(), e);
            }
        } else if (documentFile instanceof VirtualDocumentFile) {
            return ((VirtualDocumentFile) documentFile).openInputStream();

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Verify the URI is valid and permissions are still held (check persisted URI permissions)
  2. Re-acquire access via the SAF picker and takePersistableUriPermission(MODE_READ|WRITE)
  3. Catch the IOException and re-prompt the user to reselect the location

Example fix

// before
OutputStream os = path.openOutputStream();
// after
try {
    OutputStream os = path.openOutputStream();
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Could not resolve Uri")) {
        // re-request SAF access
    }
    throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure persisted SAF permission
for (UriPermissions p : context.getContentResolver().getPersistedUriPermissions()) {
    if (p.getUri().equals(treeUri) && p.isWritePermission()) return;
}
throw new IOException("No persisted write permission for " + treeUri);

Try / catch

try {
    OutputStream os = path.openOutputStream(append);
} catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Could not resolve Uri")) {
        // re-acquire access via SAF picker
    } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


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