{"record":{"id":"8fd792a8feebfbe9","repo":"MuntashirAkon/AppManager","slug":"path-cannot-be-opened-for-both-writing","errorCode":null,"errorMessage":"+ path + cannot be opened for both writing.","messagePattern":"\\+ path \\+ cannot be opened for both writing\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/io/github/muntashirakon/io/fs/VirtualFileSystem.java","lineNumber":1011,"sourceCode":"        boolean read = false;\n        boolean write = false;\n        if ((mode & MODE_READ_WRITE) != 0) {\n            read = true;\n            write = true;\n        } else if ((mode & MODE_READ_ONLY) != 0) {\n            read = true;\n        } else if ((mode & MODE_WRITE_ONLY) != 0) {\n            write = true;\n        } else {\n            throw new IllegalArgumentException(\"Bad mode: \" + mode);\n        }\n\n        if (read && write && !checkAccess(path, OsConstants.R_OK | OsConstants.W_OK)) {\n            throw new IOException(path + \" cannot be opened for both reading and writing.\");\n        } else if (read && !checkAccess(path, OsConstants.R_OK)) {\n            throw new IOException(path + \" cannot be opened for both reading.\");\n        } else if (write && !checkAccess(path, OsConstants.W_OK)) {\n            throw new IOException(path + \" cannot be opened for both writing.\");\n        }\n        Node<?> targetNode = getNode(path);\n        if (targetNode == null) {\n            throw new FileNotFoundException(path + \" does not exist.\");\n        }\n        if (!targetNode.isFile()) {\n            throw new IOException(path + \" is not a file.\");\n        }\n        return FileSystemManager.getLocal().openChannel(getCachedFile(targetNode, write), mode);\n    }\n\n    @NonNull\n    public ParcelFileDescriptor openFileDescriptor(String path, int mode) throws IOException {\n        boolean read = false;\n        boolean write = false;\n        if ((mode & MODE_READ_WRITE) != 0) {\n            read = true;\n            write = true;","sourceCodeStart":993,"sourceCodeEnd":1029,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/io/fs/VirtualFileSystem.java#L993-L1029","documentation":"VirtualFileSystem.openChannel(path, mode) throws this IOException when mode requires write and checkAccess(path, OsConstants.W_OK) fails — the path is not writable. (The message string has a copy-paste bug saying \"both writing\"; the condition is the write-only branch.)","triggerScenarios":"openChannel with MODE_WRITE_ONLY or MODE_READ_WRITE (write check) on a read-only mount, a file without write permission bits, or a location the current process cannot modify.","commonSituations":"Patching files on /system or a read-only SAF grant; editing another app's data without root; disk-full or error-remounted read-only filesystem.","solutions":["Check checkAccess(path, W_OK) before opening and fall back to a writable copy","Mount the source with write support or use a privileged/root mount if intended","Request host-OS write permissions","If only reading is needed, switch to MODE_READ_ONLY"],"exampleFix":"// before\nFileChannel ch = vfs.openChannel(\"/system/etc/hosts\", MODE_WRITE_ONLY); // read-only\n// after\nFileChannel ch = vfs.checkAccess(path, OsConstants.W_OK)\n    ? vfs.openChannel(path, MODE_WRITE_ONLY)\n    : vfs.openChannel(copyToWritable(path), MODE_WRITE_ONLY);","handlingStrategy":"try-catch","validationCode":"boolean writable = vfs.checkAccess(path, OsConstants.W_OK);","typeGuard":null,"tryCatchPattern":"try {\n    FileChannel ch = vfs.openChannel(path, MODE_WRITE_ONLY);\n} catch (IOException e) {\n    // fall back to a writable copy or surface read-only UI state\n}","preventionTips":["Pre-flight W_OK before write opens","Use MODE_READ_ONLY when only reading, to avoid write checks entirely","Check host-OS write permissions and filesystem mount flags"],"tags":["filesystem","virtual-fs","write-access"],"backgroundTag":"permission-denied","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}