{"record":{"id":"f78a8ae343a3e84e","repo":"apache/pulsar","slug":"fromindex-0-fromindex","errorCode":null,"errorMessage":"fromIndex < 0: <fromIndex>","messagePattern":"fromIndex < 0: <fromIndex>","errorType":"validation","errorClass":"IndexOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"pulsar-common/src/main/java/org/apache/pulsar/common/util/collections/BitSetRecyclable.java","lineNumber":339,"sourceCode":"     * temporarily violating the invariants.  The caller must\n     * restore the invariants before returning to the user,\n     * possibly using recalculateWordsInUse().\n     * @param wordIndex the index to be accommodated.\n     */\n    private void expandTo(int wordIndex) {\n        int wordsRequired = wordIndex+1;\n        if (wordsInUse < wordsRequired) {\n            ensureCapacity(wordsRequired);\n            wordsInUse = wordsRequired;\n        }\n    }\n\n    /**\n     * Checks that fromIndex ... toIndex is a valid range of bit indices.\n     */\n    private static void checkRange(int fromIndex, int toIndex) {\n        if (fromIndex < 0)\n            throw new IndexOutOfBoundsException(\"fromIndex < 0: \" + fromIndex);\n        if (toIndex < 0)\n            throw new IndexOutOfBoundsException(\"toIndex < 0: \" + toIndex);\n        if (fromIndex > toIndex)\n            throw new IndexOutOfBoundsException(\"fromIndex: \" + fromIndex +\n                \" > toIndex: \" + toIndex);\n    }\n\n    /**\n     * Sets the bit at the specified index to the complement of its\n     * current value.\n     *\n     * @param  bitIndex the index of the bit to flip\n     * @throws IndexOutOfBoundsException if the specified index is negative\n     * @since  1.4\n     */\n    public void flip(int bitIndex) {\n        if (bitIndex < 0)\n            throw new IndexOutOfBoundsException(\"bitIndex < 0: \" + bitIndex);","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-common/src/main/java/org/apache/pulsar/common/util/collections/BitSetRecyclable.java#L321-L357","documentation":"BitSetRecyclable.checkRange validates a [fromIndex, toIndex) bit-index range before flip/set/clear/get operate on it, and throws IndexOutOfBoundsException(\"fromIndex < 0: \" + fromIndex) when fromIndex is negative. The check mirrors java.util.BitSet so callers get the same fail-fast semantics; toIndex and ordering are checked separately. The exception propagates out of whichever public method (flip, set, clear, get) invoked checkRange.","triggerScenarios":"Calling flip(int), set(int), clear(int) or get(int) with a negative single index (fromIndex == toIndex == the negative value), or range variants flip/set/clear/get(fromIndex, toIndex) with fromIndex < 0 — e.g. bit indices derived from uninitialized values, decoded lengths, or arithmetic on empty data.","commonSituations":"Using a sentinel -1 ('bit not found') directly as a bit index from indexOf-style lookups; decoding a bit position from wire data that was truncated or corrupted; off-by-one arithmetic such as (position - offset) where offset > position; iterating from lastIndex computed as length-1 when length is 0.","solutions":["Validate the index before the call: if (idx < 0) skip/handle, or clamp with Math.max(0, idx) when that matches your intent.","If the index comes from a lookup that can return -1, check for the sentinel before using it as a bit position.","For range calls, ensure fromIndex >= 0 and fromIndex <= toIndex (ordering violations raise a different message from the same method).","If the position is derived from parsed data, validate it against the expected bit-set size before mutating."],"exampleFix":"// before\nint bit = findBit(key); // returns -1 when absent\nbitSet.set(bit);\n\n// after\nint bit = findBit(key);\nif (bit >= 0) {\n    bitSet.set(bit);\n}","handlingStrategy":"validation","validationCode":"static void requireValidBitIndex(int idx) {\n    if (idx < 0) throw new IllegalArgumentException(\"bit index must be >= 0, got \" + idx + \" (lookup miss?)\");\n}","typeGuard":"static boolean isValidBitIndex(int idx) { return idx >= 0; }","tryCatchPattern":"try {\n    bitSet.set(index);\n} catch (IndexOutOfBoundsException e) {\n    log.warn(\"Ignoring invalid bit index {} ({} )\", index, e.getMessage());\n    // skip or convert to a domain error depending on caller contract\n}","preventionTips":["Always check indexOf-style results for -1 before using them as bit positions.","Validate bit positions parsed from external data against expected maximum size.","Use java.util.OptionalInt (or isPresent checks) for lookups so a miss can't silently become an index.","Add a guard method like requireValidBitIndex around all bitSet mutations in shared code."],"tags":["java","bitset","index-out-of-bounds"],"backgroundTag":"negative-array-index","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}