{"record":{"id":"5fa3b0430df9c390","repo":"apache/cassandra","slug":"attempted-skipbytes-on-a-closed-rar","errorCode":null,"errorMessage":"Attempted skipBytes() on a closed RAR","messagePattern":"Attempted skipBytes\\(\\) on a closed RAR","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/io/util/RandomAccessReader.java","lineNumber":245,"sourceCode":"        if (newPosition >= bufferOffset && newPosition < bufferOffset + buffer.limit())\n        {\n            buffer.position((int) (newPosition - bufferOffset));\n            return;\n        }\n\n        if (newPosition > length())\n            throw new IllegalArgumentException(String.format(\"Unable to seek to position %d in %s (%d bytes) in read-only mode\",\n                                                         newPosition, getPath(), length()));\n        reBufferAt(newPosition);\n    }\n\n    @Override\n    public int skipBytes(int n) throws IOException\n    {\n        if (n <= 0)\n            return 0;\n        if (buffer == null)\n            throw new IOException(\"Attempted skipBytes() on a closed RAR\");\n        long current = current();\n        long newPosition = Math.min(current + n, length());\n        n = (int)(newPosition - current);\n        seek(newPosition);\n        return n;\n    }\n\n    /**\n     * Reads a line of text form the current position in this file. A line is\n     * represented by zero or more characters followed by {@code '\\n'}, {@code\n     * '\\r'}, {@code \"\\r\\n\"} or the end of file marker. The string does not\n     * include the line terminating sequence.\n     * <p>\n     * Blocks until a line terminating sequence has been read, the end of the\n     * file is reached or an exception is thrown.\n     * </p>\n     * @return the contents of the line or {@code null} if no characters have\n     * been read before the end of the file has been reached.","sourceCodeStart":227,"sourceCodeEnd":263,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/util/RandomAccessReader.java#L227-L263","documentation":"RandomAccessReader.skipBytes(n) throws IOException when the reader's buffer is null, i.e. the reader was closed. Like the seek-after-close error, this is a use-after-close bug, but it surfaces as IOException because skipBytes implements the InputStream contract.","triggerScenarios":"Calling skipBytes() after close() — from skipEntryRemainder, readPartition/readUnfiltered loops, or tests, when a reader handle outlives its owner's close (e.g. an iterator closed upstream but the partition-deserialization loop keeps skipping).","commonSituations":"Closing a reader while a row/partition deserialization is still in progress; exception paths that close the reader mid-read and then a finally block attempts to skip remaining entry bytes; shared reader handles across threads where one closes early.","solutions":["Ensure the reader stays open until all partition/entry reads (including skipEntryRemainder) complete","Check isClosed() before calling skipBytes and abort the read loop if closed","Fix control flow so a mid-read exception does not trigger both close and further skip calls","Use a single owner/thread for the reader lifecycle to avoid premature closes"],"exampleFix":"// before\n} finally {\n    reader.close();\n}\nskipEntryRemainder(reader); // IOException: closed RAR\n// after\ntry {\n    readEntry(reader);\n    skipEntryRemainder(reader);\n} finally {\n    reader.close();\n}","handlingStrategy":"try-catch","validationCode":"if (reader.isClosed()) return; // or abort read loop\nreader.skipBytes(n);","typeGuard":"boolean canSkip = reader != null && !reader.isClosed();","tryCatchPattern":"try { reader.skipBytes(n); } catch (IOException e) { /* abort entry processing; reader was closed */ }","preventionTips":["Close readers only after entry reads complete","Never close mid-deserialization; set a stop flag instead","Single-owner reader lifecycle"],"tags":["io","randomaccessreader","closed-resource"],"backgroundTag":"invalid-state-transition","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}