apache/cassandra · error · IllegalArgumentException
Unable to seek to position
Error message
Unable to seek to position %d in %s (%d bytes) in read-only mode
What it means
RandomAccessReader is read-only over a fixed file length, so seek() rejects any position greater than length() with a formatted IllegalArgumentException naming the position, file path, and total size. Unlike a RandomAccessFile, you cannot seek past EOF to extend a read-only view.
Solutions
- Clamp the target: seek(Math.min(offset, reader.length())) or skip the read when offset >= length()
- Validate offsets read from file metadata against the actual file size before seeking
- Run sstable verify/scrub — offsets past EOF usually indicate corruption
- Check that you opened the correct/complete file (not a partially-copied one) so length() matches expectations
Example fix
// before
reader.seek(commitLogSegmentMarkerOffset); // may exceed length
// after
if (markerOffset >= 0 && markerOffset < reader.length()) {
reader.seek(markerOffset);
} else {
break; // corrupted or truncated file, stop scanning
} Defensive patterns
Strategy: validation
Validate before calling
if (offset >= 0 && offset < reader.length()) reader.seek(offset); else stopReading();
Type guard
boolean inBounds = offset >= 0 && offset < reader.length();
Try / catch
try { reader.seek(offset); } catch (IllegalArgumentException e) { throw new CorruptFileException(e.getMessage()); } Prevention
- Bounds-check offsets against length() before seek
- Distrust stored offsets in files that may be truncated
- Verify sstables after unclean shutdown
When it happens
Trigger: Calling seek(pos) where pos > length() — from readSyncMarker scanning near end-of-file with bogus marker offsets, keyIterator/keyReader using corrupt index offsets, or caller-supplied offsets from a corrupted/truncated file whose declared length exceeds the actual file.
Common situations: Corrupted sstable segments where stored offsets point past EOF; reading a file that was truncated after its length metadata was written; off-by-one on file size (using size+1) or wrong units (bytes vs. chunks).
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- new position should not be negative
- Attempted skipBytes() on a closed RAR
- Attempted to seek in a closed RAR
- Length must be positive
- Length must not be negative
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/5f88d665d3002b47.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/io/util/RandomAccessReader.java:234
@Override
public void seek(long newPosition)
{
if (newPosition < 0)
throw new IllegalArgumentException("new position should not be negative");
if (buffer == null)
throw new IllegalStateException("Attempted to seek in a closed RAR");
long bufferOffset = bufferHolderOffset;
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;
}
View on GitHub (pinned to 88fd0f6a0e)