{"record":{"id":"ebf2a6d7084d971c","repo":"apache/cassandra","slug":"new-position-should-not-be-negative","errorCode":null,"errorMessage":"new position should not be negative","messagePattern":"new position should not be negative","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/io/util/RandomAccessReader.java","lineNumber":221,"sourceCode":"\n    /**\n     * Class to hold a mark to the position of the file\n     */\n    private static class BufferedRandomAccessFileMark implements DataPosition\n    {\n        final long pointer;\n\n        private BufferedRandomAccessFileMark(long pointer)\n        {\n            this.pointer = pointer;\n        }\n    }\n\n    @Override\n    public void seek(long newPosition)\n    {\n        if (newPosition < 0)\n            throw new IllegalArgumentException(\"new position should not be negative\");\n\n        if (buffer == null)\n            throw new IllegalStateException(\"Attempted to seek in a closed RAR\");\n\n        long bufferOffset = bufferHolderOffset;\n        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","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/util/RandomAccessReader.java#L203-L239","documentation":"RandomAccessReader.seek(newPosition) validates that the target offset is non-negative before moving the read cursor. Negative offsets cannot exist in a file, so this indicates a caller bug (underflow or bad offset arithmetic) and throws IllegalArgumentException.","triggerScenarios":"Calling rar.seek(negativeLong) — commonly from callers like readSyncMarker, keyIterator/keyReader, createReader, reset, or skipBytes when an offset computation underflows (e.g. position - size where size > position) or a corrupted length/offset field is read from disk and used directly.","commonSituations":"Reading a corrupted or partially-written sstable whose stored offsets are bogus; subtracting a header size from offset 0; using unsigned values read from disk in signed long math.","solutions":["Validate offsets read from files before seeking (reject negatives with a clear corrupt-file error)","Clamp: if (off >= 0) seek(off) else throw/handle corruption","Fix the offset arithmetic so it cannot underflow (e.g. check minuend >= subtrahend)","Run an sstable verify/scrub — a negative offset usually means on-disk corruption"],"exampleFix":"// before\nlong offset = readLongFromFile() - headerSize; // may underflow\nreader.seek(offset);\n// after\nlong offset = readLongFromFile() - headerSize;\nif (offset < 0)\n    throw new CorruptFileException(\"negative offset \" + offset);\nreader.seek(offset);","handlingStrategy":"validation","validationCode":"if (offset < 0) throw new CorruptFileException(\"negative offset: \" + offset); reader.seek(offset);","typeGuard":"boolean seekable = offset >= 0 && offset <= reader.getLength();","tryCatchPattern":"try { reader.seek(offset); } catch (IllegalArgumentException e) { throw new CorruptFileException(e.getMessage()); }","preventionTips":["Validate offsets read from disk before use","Watch for long underflow in offset math","Scrub corrupt files rather than trusting stored offsets"],"tags":["io","randomaccessreader","validation"],"backgroundTag":"invalid-argument-value","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"}