ipfs/kubo · error

Provide.BloomFPRate must be >= %d (1 in 1M), got %d

Error message

Provide.BloomFPRate must be >= %d (1 in 1M), got %d

What it means

ValidateProvideConfig checks Provide.BloomFPRate, the bloom-filter false-positive denominator used by +unique/+entities reprovide cycles. Below 1,000,000 (one false positive per million lookups) the filter becomes lossy enough to silently skip a meaningful fraction of CIDs from each reprovide cycle, so kubo rejects such values instead of degrading announcements invisibly.

Source

Thrown at config/provide.go:207

	if err != nil {
		panic(err)
	}
	return strategy
}

// ValidateProvideConfig validates the Provide configuration according to DHT requirements.
func ValidateProvideConfig(cfg *Provide) error {
	// Validate Provide.Strategy
	strategy := cfg.Strategy.WithDefault(DefaultProvideStrategy)
	if _, err := ParseProvideStrategy(strategy); err != nil {
		return fmt.Errorf("Provide.Strategy: %w", err)
	}

	// Validate Provide.BloomFPRate
	if !cfg.BloomFPRate.IsDefault() {
		rate := cfg.BloomFPRate.WithDefault(DefaultProvideBloomFPRate)
		if rate < MinProvideBloomFPRate {
			return fmt.Errorf("Provide.BloomFPRate must be >= %d (1 in 1M), got %d", MinProvideBloomFPRate, rate)
		}
	}

	// Validate Provide.DHT.Interval
	if !cfg.DHT.Interval.IsDefault() {
		interval := cfg.DHT.Interval.WithDefault(DefaultProvideDHTInterval)
		if interval > amino.DefaultProvideValidity {
			return fmt.Errorf("Provide.DHT.Interval (%v) must be less than or equal to DHT provider record validity (%v)", interval, amino.DefaultProvideValidity)
		}
		if interval < 0 {
			return fmt.Errorf("Provide.DHT.Interval must be non-negative, got %v", interval)
		}
		// Provide.DHT.Interval=0 used to disable the entire provide system as a
		// side effect. It now disables only the periodic reprovide schedule:
		// new CIDs still announce via fast-provide-root and 'ipfs provide once'.
		// Operators upgrading from earlier kubo versions must opt in to one of
		// the two semantics by setting Provide.Enabled explicitly:
		//   - Provide.Enabled=false fully disables providing (the old behaviour).

View on GitHub (pinned to 329838acdf)

Solutions

  1. Raise Provide.BloomFPRate to at least 1,000,000 (the default is 4,750,000)
  2. Remove the Provide.BloomFPRate key to use the default rate
  3. If memory pressure motivated the low value, reduce content instead (e.g. fewer pinned DAGs) rather than accepting a lossy filter

Example fix

// before (config file)
"BloomFPRate": 10000
// after
"BloomFPRate": 4750000
Defensive patterns

Strategy: validation

Validate before calling

rate := cfg.Provide.BloomFPRate.WithDefault(config.DefaultProvideBloomFPRate)
if !cfg.Provide.BloomFPRate.IsDefault() && rate < config.MinProvideBloomFPRate {
	return fmt.Errorf("BloomFPRate %d below minimum %d", rate, config.MinProvideBloomFPRate)
}

Try / catch

if err := config.ValidateProvideConfig(cfg.Provide); err != nil {
	if strings.Contains(err.Error(), "BloomFPRate") {
		cfg.Provide.BloomFPRate = nil // fall back to default
	}
	return err
}

Prevention

When it happens

Trigger: Node startup (ValidateProvideConfig called from IPFS init) when Provide.BloomFPRate is explicitly set (not default) to a value below MinProvideBloomFPRate = 1_000_000, e.g. 10_000.

Common situations: Operator tuning the bloom filter to save memory picks an aggressive small N; copied config from an example or older version using a lower rate; misunderstanding that a lower number means a better rate (it is 1/N, so higher is better).

Related errors


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