ipfs/kubo · error

bloom tracker

Error message

bloom tracker: %w

What it means

Returned when walker.NewBloomTracker fails to allocate the bloom-filter VisitedTracker used by '+unique' (and '+entities') reprovide cycles. The bloom filter is sized from the previous cycle's unique CID count with a growth margin; a failure here means the bloom/tracker could not be constructed (typically an allocation or sizing failure). Without it, the deduplicated walk cannot start.

Solutions

  1. Check the wrapped error in logs and node memory availability
  2. Inspect/reset the datastore key holding the persisted unique count (readLastUniqueCount source) to clear a corrupt huge count
  3. Validate Provide.BloomFPRate / strategy values in the kubo config are sane
  4. Retry on the next reprovide cycle; transient OOM may succeed with more free memory
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check persisted count before cycle
count := readLastUniqueCount(ds)
if count > maxReasonableCIDs {
    // reset or log suspicion of corruption
}

Try / catch

tracker, err := walker.NewBloomTracker(uint(expectedItems), fpRate)
if err != nil {
    return nil, fmt.Errorf("bloom tracker: %w", err)
}

Prevention

When it happens

Trigger: Reprovide cycle with Provide.Strategy containing '+unique' where NewBloomTracker(expectedItems, fpRate) errors — usually because the persisted previous count read from the datastore is enormous/corrupt (8-byte big-endian value) leading to an impractically large bloom allocation, or an invalid FP-rate config.

Common situations: Corrupted value under the last-unique-count datastore key producing a huge expectedItems, memory-constrained hosts, or a misconfigured Provide.BloomFPRate.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/445bd1cf0f43760d. Report an issue: GitHub.

Appendix: source

Thrown at core/node/provider.go:1342

			count := readLastUniqueCount(ds)
			// size the bloom from the previous cycle's count (with growth
			// margin for repo changes between cycles), falling back to
			// DefaultBloomInitialCapacity on the very first cycle. The
			// bloom chain auto-grows if the repo exceeds this estimate.
			expectedItems := max(
				uint64(walker.DefaultBloomInitialCapacity),
				uint64(float64(count)*walker.BloomGrowthMargin),
			)
			// the tracker is shared across all sub-walks (MFS, recursive
			// pins, direct pins) within a single reprovide cycle. it
			// detects duplicate sub-DAG branches across recursive pins
			// that share content (e.g. append-only datasets where each
			// version differs by a small delta). when a CID is already
			// in the bloom, its entire subtree is skipped, reducing
			// traversal from O(pins * total_blocks) to O(unique_blocks).
			tracker, err := walker.NewBloomTracker(uint(expectedItems), fpRate)
			if err != nil {
				return nil, fmt.Errorf("bloom tracker: %w", err)
			}

			useEntities := strategyFlag&config.ProvideStrategyEntities != 0

			// select provider functions based on +entities modifier:
			// +entities uses WalkEntityRoots (skips file chunks),
			// +unique without +entities uses WalkDAG (all blocks).
			makePinProv := dspinner.NewUniquePinnedProvider
			makeMFSProv := uniqueMFSProvider
			if useEntities {
				makePinProv = dspinner.NewPinnedEntityRootsProvider
				makeMFSProv = mfsEntityRootsProvider
			}

			var inner provider.KeyChanFunc
			switch {
			case basePinned && baseMFS:
				// MFS first: walk MFS (locality-filtered), then pinned.

View on GitHub (pinned to 329838acdf)