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

  1. Clamp the target: seek(Math.min(offset, reader.length())) or skip the read when offset >= length()
  2. Validate offsets read from file metadata against the actual file size before seeking
  3. Run sstable verify/scrub — offsets past EOF usually indicate corruption
  4. 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

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


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)