MuntashirAkon/AppManager · error · IOException
+ path + cannot be opened for both reading.
Error message
+ path + cannot be opened for both reading.
What it means
VirtualFileSystem.openChannel(path, mode) throws this IOException when mode requires read and checkAccess(path, OsConstants.R_OK) fails — the path is not readable. Note the message string itself has a copy-paste bug ("cannot be opened for both reading."), but the condition is the read-only branch of the access pre-flight.
Source
Thrown at app/src/main/java/io/github/muntashirakon/io/fs/VirtualFileSystem.java:1009
@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;
boolean write = false;
if ((mode & MODE_READ_WRITE) != 0) {View on GitHub (pinned to 0152f468fc)
Solutions
- Confirm the path is readable via checkAccess(path, R_OK) before opening
- Request the needed host-OS permissions or use a provider/mount with read access
- If root/privileged access is expected, verify the privileged mount is actually active
- If the file should be writable, note you still need read permission for read-write mode
Example fix
// before
FileChannel ch = vfs.openChannel("/data/data/other.app/db", MODE_READ_ONLY); // no read access
// after
if (!vfs.checkAccess(path, OsConstants.R_OK)) {
requestAccessOrEscalate(path); // e.g. root/SAF flow
}
FileChannel ch = vfs.openChannel(path, MODE_READ_ONLY); Defensive patterns
Strategy: try-catch
Validate before calling
boolean readable = vfs.checkAccess(path, OsConstants.R_OK);
Try / catch
try {
FileChannel ch = vfs.openChannel(path, MODE_READ_ONLY);
} catch (IOException e) {
// trigger permission/privilege acquisition flow
} Prevention
- Pre-flight R_OK before read opens
- Note the misleading "both reading" message text — it still means a failed read-access check
- Verify the privileged/root mount is active for protected paths
When it happens
Trigger: Calling openChannel with MODE_READ_ONLY (or MODE_READ_WRITE where the read check fails first... it does not — this branch is read-only) on a file the caller cannot read: restricted directory, permission bits, or a provider denying reads.
Common situations: Reading another app's private files without root; file with 0600 owned by a different UID; SELinux/AppArmor restriction on the backing path; broken provider authorization.
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
- + path + does not exist.
- + path + is not a file.
- Bad mode: + mode
- + path + cannot be opened for both reading and writing.
- + path + cannot be opened for both writing.
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/9a032359ad3882ac.
Report an issue: GitHub.