#6403·paradedb

Bitmap intersection rescan: "stream (consumer N, segment X) claimed twice" on 0.25.6

Author: cq-guojiaCreated Sep 18, 2026Updated Sep 18, 2026

Summary

On paradedb/paradedb:0.25.6-pg18, a query that combines a BM25 @@@ search with a heap-filter predicate covered by a btree index fails with:

InternalServerError: bitmap intersection stream (consumer 0, segment <uuid>) claimed twice

The segment UUID differs on every failure → a rescan state-reset bug, not a corrupted index.

Environment

  • Image: paradedb/paradedb:0.25.6-pg18 (Postgres 18 + pg_search)
  • The error is still present on 0.25.6, which already includes both #6118 (fix: Bitmap intersection children were dropped by CustomPathBuilder::build on 0.25.x, 2026-08-27, merged before the 0.25.6 tag) and #6092 (per-rescan DSA free). So this appears to be a separate, still-unfixed bitmap-intersection rescan issue.
  • Not fixed in v0.25.9 either (checked the release commit history — no bitmap-intersection / claimed-twice related commit).

Reproduction

sql
SET paradedb.enable_bitmap_intersection = on;   -- default

EXPLAIN (COSTS OFF)
SELECT id FROM memory_units
WHERE bank_id = 'Agent::NAS-Docker' AND fact_type = 'observation'
  AND id @@@ paradedb.boolean(should => ARRAY[
        paradedb.match('text', '测试'),
        paradedb.match('context', '测试'),
        paradedb.match('text_signals', '测试')])
ORDER BY paradedb.score(id) DESC LIMIT 10;

Plan (note the bitmap intersection path):

Limit
->  Custom Scan (ParadeDB Base Scan) on memory_units
    Index: idx_memory_units_text_search
    Bitmap Intersection: idx_memory_units_bank_fact_type   <-- triggers the bug
    "uses_tid_bitmap":true,"bitmap_consumer_id":0
    "uses_tid_bitmap":true,"bitmap_consumer_id":1

The bitmap_consumer_id in the plan is exactly the consumer N in the error — it is a bitmap consumer, not a parallel worker (this was initially misdiagnosed as a parallel-scan issue; it is not).

In our workload this scan sits on the inner side of a nested loop and is rescanned repeatedly, which is when the error fires.

Root cause (hypothesis)

bank_id = ? AND fact_type = ? is covered by the btree index idx_memory_units_bank_fact_type, so pg_search builds a bitmap from it to pre-filter documents (the paradedb.enable_bitmap_intersection feature, default on). On rescan of the custom scan, the bitmap-intersection stream / consumer state is not reset correctly, so the same segment is consumed twice → claimed twice.

Workaround

Two settings are required together. Disabling only bitmap_intersection makes the planner pick a parallel plan, which then hits a separate unfixed race (paradedb#6112, not cherry-picked into 0.25.x) that silently returns duplicated rows:

sql
SET paradedb.enable_bitmap_intersection = off;
SET max_parallel_workers_per_gather = 0;

After both are set, EXPLAIN shows a clean serial Custom Scan with always_filters heap filtering (no Bitmap Intersection, no Gather). The query then runs correctly.

Suggested fix

On rescan of a ParadeDB base scan that uses bitmap intersection, fully re-initialize / reset the bitmap-intersection stream and consumer state before each rescan, rather than reusing the prior state.

Related

  • #6118 — "Bitmap intersection children were dropped by CustomPathBuilder::build" (already in 0.25.6; does not fix this)
  • #6092 — "Bitmap intersection: free the per-rescan DSA allocation" (a different per-rescan issue)
  • paradedb#6112 — parallel rescan race (not in 0.25.x; the reason the workaround above also needs max_parallel_workers_per_gather=0)