apache/cassandra · error · IOException
Attempted skipBytes() on a closed RAR
Error message
Attempted skipBytes() on a closed RAR
What it means
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.
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
Example fix
// before
} finally {
reader.close();
}
skipEntryRemainder(reader); // IOException: closed RAR
// after
try {
readEntry(reader);
skipEntryRemainder(reader);
} finally {
reader.close();
} Defensive patterns
Strategy: try-catch
Validate before calling
if (reader.isClosed()) return; // or abort read loop reader.skipBytes(n);
Type guard
boolean canSkip = reader != null && !reader.isClosed();
Try / catch
try { reader.skipBytes(n); } catch (IOException e) { /* abort entry processing; reader was closed */ } Prevention
- Close readers only after entry reads complete
- Never close mid-deserialization; set a stop flag instead
- Single-owner reader lifecycle
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Attempted to seek in a closed RAR
- new position should not be negative
- Unable to seek to position
- Ballot file corrupted
- Can't open %r for reading
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/5fa3b0430df9c390.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/io/util/RandomAccessReader.java:245
if (newPosition >= bufferOffset && newPosition < bufferOffset + buffer.limit())
{
buffer.position((int) (newPosition - bufferOffset));
return;
}
if (newPosition > length())
throw new IllegalArgumentException(String.format("Unable to seek to position %d in %s (%d bytes) in read-only mode",
newPosition, getPath(), length()));
reBufferAt(newPosition);
}
@Override
public int skipBytes(int n) throws IOException
{
if (n <= 0)
return 0;
if (buffer == null)
throw new IOException("Attempted skipBytes() on a closed RAR");
long current = current();
long newPosition = Math.min(current + n, length());
n = (int)(newPosition - current);
seek(newPosition);
return n;
}
/**
* Reads a line of text form the current position in this file. A line is
* represented by zero or more characters followed by {@code '\n'}, {@code
* '\r'}, {@code "\r\n"} or the end of file marker. The string does not
* include the line terminating sequence.
* <p>
* Blocks until a line terminating sequence has been read, the end of the
* file is reached or an exception is thrown.
* </p>
* @return the contents of the line or {@code null} if no characters have
* been read before the end of the file has been reached.View on GitHub (pinned to 88fd0f6a0e)