apache/pulsar · error · IndexOutOfBoundsException

fromIndex < 0: <fromIndex>

Error message

fromIndex < 0: <fromIndex>

What it means

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.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/collections/BitSetRecyclable.java:339

     * temporarily violating the invariants.  The caller must
     * restore the invariants before returning to the user,
     * possibly using recalculateWordsInUse().
     * @param wordIndex the index to be accommodated.
     */
    private void expandTo(int wordIndex) {
        int wordsRequired = wordIndex+1;
        if (wordsInUse < wordsRequired) {
            ensureCapacity(wordsRequired);
            wordsInUse = wordsRequired;
        }
    }

    /**
     * Checks that fromIndex ... toIndex is a valid range of bit indices.
     */
    private static void checkRange(int fromIndex, int toIndex) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex < 0: " + fromIndex);
        if (toIndex < 0)
            throw new IndexOutOfBoundsException("toIndex < 0: " + toIndex);
        if (fromIndex > toIndex)
            throw new IndexOutOfBoundsException("fromIndex: " + fromIndex +
                " > toIndex: " + toIndex);
    }

    /**
     * Sets the bit at the specified index to the complement of its
     * current value.
     *
     * @param  bitIndex the index of the bit to flip
     * @throws IndexOutOfBoundsException if the specified index is negative
     * @since  1.4
     */
    public void flip(int bitIndex) {
        if (bitIndex < 0)
            throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);

View on GitHub (pinned to 820761864e)

Solutions

  1. Validate the index before the call: if (idx < 0) skip/handle, or clamp with Math.max(0, idx) when that matches your intent.
  2. If the index comes from a lookup that can return -1, check for the sentinel before using it as a bit position.
  3. For range calls, ensure fromIndex >= 0 and fromIndex <= toIndex (ordering violations raise a different message from the same method).
  4. If the position is derived from parsed data, validate it against the expected bit-set size before mutating.

Example fix

// before
int bit = findBit(key); // returns -1 when absent
bitSet.set(bit);

// after
int bit = findBit(key);
if (bit >= 0) {
    bitSet.set(bit);
}
Defensive patterns

Strategy: validation

Validate before calling

static void requireValidBitIndex(int idx) {
    if (idx < 0) throw new IllegalArgumentException("bit index must be >= 0, got " + idx + " (lookup miss?)");
}

Type guard

static boolean isValidBitIndex(int idx) { return idx >= 0; }

Try / catch

try {
    bitSet.set(index);
} catch (IndexOutOfBoundsException e) {
    log.warn("Ignoring invalid bit index {} ({} )", index, e.getMessage());
    // skip or convert to a domain error depending on caller contract
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/f78a8ae343a3e84e. Report an issue: GitHub.