MuntashirAkon/AppManager · error · IOException

+ path + cannot be opened for both reading and writing.

Error message

+ path + cannot be opened for both reading and writing.

What it means

VirtualFileSystem.openChannel(path, mode) throws this IOException when mode requires both read and write but checkAccess(path, R_OK|W_OK) fails — the VFS reports the path cannot be opened for read+write. (The message text is misleading if only write was intended; it is thrown strictly in the read&&write branch.)

Source

Thrown at app/src/main/java/io/github/muntashirakon/io/fs/VirtualFileSystem.java:1007

    }

    @NonNull
    public FileChannel openChannel(String path, int mode) throws IOException {
        boolean read = false;
        boolean write = false;
        if ((mode & MODE_READ_WRITE) != 0) {
            read = true;
            write = true;
        } else if ((mode & MODE_READ_ONLY) != 0) {
            read = true;
        } else if ((mode & MODE_WRITE_ONLY) != 0) {
            write = true;
        } else {
            throw new IllegalArgumentException("Bad mode: " + mode);
        }

        if (read && write && !checkAccess(path, OsConstants.R_OK | OsConstants.W_OK)) {
            throw new IOException(path + " cannot be opened for both reading and writing.");
        } else if (read && !checkAccess(path, OsConstants.R_OK)) {
            throw new IOException(path + " cannot be opened for both reading.");
        } else if (write && !checkAccess(path, OsConstants.W_OK)) {
            throw new IOException(path + " cannot be opened for both writing.");
        }
        Node<?> targetNode = getNode(path);
        if (targetNode == null) {
            throw new FileNotFoundException(path + " does not exist.");
        }
        if (!targetNode.isFile()) {
            throw new IOException(path + " is not a file.");
        }
        return FileSystemManager.getLocal().openChannel(getCachedFile(targetNode, write), mode);
    }

    @NonNull
    public ParcelFileDescriptor openFileDescriptor(String path, int mode) throws IOException {
        boolean read = false;

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Open with MODE_READ_ONLY if writing is not actually required
  2. Remount/choose a writable provider or copy the file to a writable location before read-write access
  3. Verify host-OS storage permissions are granted
  4. Check writability via checkAccess(path, R_OK|W_OK) before opening

Example fix

// before
FileChannel ch = vfs.openChannel(path, MODE_READ_WRITE); // read-only mount
// after
if (vfs.checkAccess(path, OsConstants.R_OK | OsConstants.W_OK)) {
    FileChannel ch = vfs.openChannel(path, MODE_READ_WRITE);
} else {
    FileChannel ch = vfs.openChannel(path, MODE_READ_ONLY);
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean canReadWrite = vfs.checkAccess(path, OsConstants.R_OK | OsConstants.W_OK);

Try / catch

try {
    FileChannel ch = vfs.openChannel(path, MODE_READ_WRITE);
} catch (IOException e) {
    // degrade to MODE_READ_ONLY or copy to a writable location
}

Prevention

When it happens

Trigger: Calling openChannel with MODE_READ_WRITE on a read-only mount or a file the caller lacks write permission for; opening a file on a provider that grants read but not write; a random-access edit on a file in a read-only location.

Common situations: In-place editing of files on a read-only mount (system partition, SAF read-only grant); missing storage permissions; file owned by another app/UID.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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