apache/pulsar · error · UnsupportedOperationException

stream is not supported

Error message

stream is not supported

What it means

ConcurrentBitSet.stream() is explicitly unsupported: the class overrides IntStream stream() only to throw UnsupportedOperationException("stream is not supported"), because materializing a stream from a lock-striped concurrent bit set cannot provide the snapshot semantics callers expect. The compiler will accept the call; the failure happens only at runtime.

Source

Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/collections/ConcurrentBitSet.java:430

        String str = super.toString();
        if (!rwLock.validate(stamp)) {
            // Fallback to read lock
            stamp = rwLock.readLock();
            try {
                str = super.toString();
            } finally {
                rwLock.unlockRead(stamp);
            }
        }
        return str;
    }

    /**
     * This operation is not supported on {@code ConcurrentBitSet}.
     */
    @Override
    public IntStream stream() {
        throw new UnsupportedOperationException("stream is not supported");
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        }
        if (!(o instanceof ConcurrentBitSet)) {
            return false;
        }
        long stamp = rwLock.tryOptimisticRead();
        boolean isEqual = super.equals(o);
        if (!rwLock.validate(stamp)) {
            // Fallback to read lock
            stamp = rwLock.readLock();
            try {
                isEqual = super.equals(o);
            } finally {
                rwLock.unlockRead(stamp);

View on GitHub (pinned to 820761864e)

Solutions

  1. Replace stream() with index-based iteration: loop i from 0 while calling nextSetBit(i) semantics if available, or use the word/index API
  2. Use the underlying get()/nextClearBit-style iteration appropriate to ConcurrentBitSet's API
  3. If a snapshot is needed, copy bits into a plain BitSet or int list under the caller's synchronization, then stream that
  4. Audit generic code paths for UnsupportedOperationException when adopting ConcurrentBitSet

Example fix

// before
IntStream indices = concurrentBitSet.stream();
// after
List<Integer> indices = new ArrayList<>();
for (int i = 0; i < concurrentBitSet.length(); i++) {
    if (concurrentBitSet.get(i)) indices.add(i);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ConcurrentBitSet does not support stream(); iterate instead
List<Integer> setBits = new ArrayList<>();
for (int i = 0; i < concurrentBitSet.length(); i++) {
    if (concurrentBitSet.get(i)) setBits.add(i);
}

Type guard

static boolean supportsStream(Object bitSet) { return !(bitSet instanceof ConcurrentBitSet); }

Try / catch

try {
    stream = bitSet.stream();
} catch (UnsupportedOperationException e) {
    // fall back to index-based iteration
    stream = indexBasedStream(bitSet);
}

Prevention

When it happens

Trigger: Calling stream() on a ConcurrentBitSet (not BitSetRecyclable) — e.g. generic code written against a BitSet-like abstraction, or refactoring code that used BitSetRecyclable/plain BitSet to use ConcurrentBitSet and kept the stream-based iteration.

Common situations: Switching a data structure to ConcurrentBitSet for thread safety without auditing all operations; library code that streams any BitSet; collecting acknowledged indices for logging/stats.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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