{"record":{"id":"9a53deac1e6223a0","repo":"oracle/graal","slug":"read-append-not-allowed","errorCode":null,"errorMessage":"READ + APPEND not allowed","messagePattern":"READ \\+ APPEND not allowed","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"espresso/src/com.oracle.truffle.espresso.io/src/sun/nio/fs/TruffleFileSystemProvider.java","lineNumber":152,"sourceCode":"        if (!readable && !writable) {\n            if (append) {\n                writable = true;\n            } else {\n                readable = true;\n            }\n        }\n\n        // set direct option\n        boolean direct = false;\n        for (OpenOption option : options) {\n            if (ExtendedOptions.DIRECT.matches(option)) {\n                direct = true;\n                break;\n            }\n        }\n        // check for Exceptions\n        if (readable && append) {\n            throw new IllegalArgumentException(\"READ + APPEND not allowed\");\n        }\n        if (append && options.contains(StandardOpenOption.TRUNCATE_EXISTING)) {\n            throw new IllegalArgumentException(\"APPEND + TRUNCATE_EXISTING not allowed\");\n        }\n\n        FileDescriptor fd = new FileDescriptor();\n        // populates fd via HostCode which opens the file and checks the permissions\n        newFileChannel0(TrufflePath.toTrufflePath(path), fd, openOptionsMask, fileAttributeMask);\n        return NewFileChannelHelper.open(fd, path.toString(), readable, writable, sync, direct, null);\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException {\n        // ALL_PERMISSIONS is the default permission on Unix.\n        int fileAttributeMask = FileAttributeParser.parseWithDefault(FileAttributeParser.ALL_PERMISSIONS, attrs);\n        createDirectory0(TrufflePath.toTrufflePath(dir), fileAttributeMask);\n    }","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/espresso/src/com.oracle.truffle.espresso.io/src/sun/nio/fs/TruffleFileSystemProvider.java#L134-L170","documentation":"Thrown by TruffleFileSystemProvider.newFileChannel when the option set contains both READ and APPEND. Opening for append positions every write at the end of the file, which is meaningless for a channel that is also readable, so the combination is rejected up front exactly as the JDK's sun.nio.fs providers do. Note that APPEND already implies WRITE.","triggerScenarios":"Files.newByteChannel(path, StandardOpenOption.READ, StandardOpenOption.APPEND) or Files.newFileChannel(...) with both flags, executed against a TrufflePath in the Espresso guest.","commonSituations":"Log-rotation code that opens a file with a generic option list built at runtime and accidentally unions READ into an append set; refactoring code that previously used RandomAccessFile.","solutions":["Drop READ and open with just APPEND (it implies WRITE) if you only append","Open with READ + WRITE and seek to the end manually if you need to read back what you wrote","Build the option set conditionally so READ is never added when APPEND is present"],"exampleFix":"// before\nFileChannel ch = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.APPEND);\n\n// after\nFileChannel ch = FileChannel.open(path, StandardOpenOption.WRITE, StandardOpenOption.APPEND);\n// or, to read and append:\nFileChannel rw = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE);\nrw.position(rw.size());","handlingStrategy":"validation","validationCode":"Set<OpenOption> opts = ...;\nif (opts.contains(StandardOpenOption.READ) && opts.contains(StandardOpenOption.APPEND)) {\n    opts.remove(StandardOpenOption.READ); // APPEND implies WRITE\n}","typeGuard":null,"tryCatchPattern":"catch (IllegalArgumentException e) when message contains 'READ + APPEND': rethrow as a configuration error naming the offending option set.","preventionTips":["Encode open modes as an enum (READ, WRITE, APPEND) and expand to options in exactly one place","Unit-test the option expansion for all modes"],"tags":["espresso","nio","file-channel","open-options","truffle"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}