{"record":{"id":"6fcf74ae2f0a8cb4","repo":"apache/cassandra","slug":"the-target-point-id-d-cannot-be-less-than-0-or","errorCode":null,"errorMessage":"The target point id [%d] cannot be less than 0 or greater than or equal to the key count [%d]","messagePattern":"The target point id \\[(.+?)\\] cannot be less than 0 or greater than or equal to the key count \\[(.+?)\\]","errorType":"exception","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/index/sai/disk/v1/keystore/KeyLookup.java","lineNumber":154,"sourceCode":"            this.nextBlockKey = new BytesRef(keyLookupMeta.maxKeyLength);\n            keysInput.seek(keysFilePointer);\n            readKey(currentPointId, currentKey);\n        }\n\n        /**\n         * Positions the cursor on the target point id and reads the key at the target to the current key buffer.\n         * <p>\n         * It is allowed to position the cursor before the first item or after the last item;\n         * in these cases the internal buffer is cleared.\n         *\n         * @param pointId point id to lookup\n         * @return The {@link ByteSource} containing the key\n         * @throws IndexOutOfBoundsException if the target point id is less than -1 or greater than the number of keys\n         */\n        public @Nonnull ByteSource seekToPointId(long pointId)\n        {\n            if (pointId < 0 || pointId >= keyLookupMeta.keyCount)\n                throw new IndexOutOfBoundsException(String.format(INDEX_OUT_OF_BOUNDS, pointId, keyLookupMeta.keyCount));\n\n            if (pointId != currentPointId)\n            {\n                long blockIndex = pointId >>> blockShift;\n                // We need to reset the block if the block index has changed or the pointId < currentPointId.\n                // We can read forward in the same block without a reset, but we can't read backwards, and token\n                // collision can result in us moving backwards.\n                if (blockIndex != currentBlockIndex || pointId < currentPointId)\n                {\n                    currentBlockIndex = blockIndex;\n                    resetToCurrentBlock();\n                }\n            }\n            while (currentPointId < pointId)\n            {\n                currentPointId++;\n                readCurrentKey();\n                updateCurrentBlockIndex(currentPointId);","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/index/sai/disk/v1/keystore/KeyLookup.java#L136-L172","documentation":"KeyLookup.seekToPointId() requires the target point id to be within [0, keyCount) before positioning its block-packed reader over the key store. Point ids are dense row ids; seeking outside that range would decode bogus key data, so it fails fast with IndexOutOfBoundsException. The javadoc notes -1 is tolerated by the adjacent seekBefore variant, but this method rejects anything below 0.","triggerScenarios":"A balanced-tree or postings iterator resolves a rowid/point id that is >= the segment metadata keyCount or negative, then calls keyLookup.seekToPointId(pointId) during a primary-key map lookup.","commonSituations":"Corrupted or mismatched SAI segment components (postings referencing rowids that no longer exist), partially-written segments after a crash, or version-skew between index descriptor and data files.","solutions":["Rebuild the affected SAI index (nodetool rebuild_index or DROP/CREATE INDEX) to regenerate consistent components.","Validate that postings rowids never exceed segmentMetadata keyCount in the writer path.","Check disk health / file corruption and restore from a clean snapshot if components are truncated."],"exampleFix":"// before\nByteSource key = keyLookup.seekToPointId(rowId);\n// after\nif (rowId >= 0 && rowId < keyLookupMeta.keyCount)\n    ByteSource key = keyLookup.seekToPointId(rowId);","handlingStrategy":"validation","validationCode":"if (pointId < 0 || pointId >= keyLookupMeta.keyCount) return null;","typeGuard":"boolean validPointId(long id, long keyCount) { return id >= 0 && id < keyCount; }","tryCatchPattern":"try { return keyLookup.seekToPointId(id); } catch (IndexOutOfBoundsException e) { log.warn(\"rowid {} out of range — corrupt segment\", id, e); return null; }","preventionTips":["Clamp postings rowids to segmentMetadata keyCount before lookups.","Rebuild SAI indexes after unclean shutdowns if corruption is suspected."],"tags":["cassandra","sai","index-corruption","bounds-check"],"backgroundTag":"index-out-of-bounds","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}