ipfs/kubo · error

+unique/+entities is incompatible with roots in %q

Error message

+unique/+entities is incompatible with roots in %q

What it means

ParseProvideStrategy accepts a plus-separated Provide.Strategy string and returns a bitmask. The deduplication modifiers +unique and +entities implement cross-DAG CID deduplication while walking whole DAGs, so they only make sense when the base strategy walks DAGs (pinned and/or mfs). The roots strategy announces only root CIDs without DAG traversal, which contradicts deduplication, so combining them is rejected with this error.

Source

Thrown at config/provide.go:179

		case "entities":
			strategy |= ProvideStrategyEntities | ProvideStrategyUnique
		default:
			return 0, fmt.Errorf("unknown provide strategy token: %q in %q", part, s)
		}
	}
	// "all" provides every block and cannot be combined with selective strategies
	if strategy&ProvideStrategyAll != 0 && strategy != ProvideStrategyAll {
		return 0, fmt.Errorf("\"all\" strategy cannot be combined with other strategies in %q", s)
	}
	// +unique/+entities require a base strategy that walks DAGs (pinned and/or mfs)
	wantsDedup := strategy&(ProvideStrategyUnique|ProvideStrategyEntities) != 0
	if wantsDedup {
		walksDAGs := strategy&(ProvideStrategyPinned|ProvideStrategyMFS) != 0
		if !walksDAGs {
			return 0, fmt.Errorf("+unique/+entities must combine with pinned and/or mfs in %q", s)
		}
		if strategy&ProvideStrategyRoots != 0 {
			return 0, fmt.Errorf("+unique/+entities is incompatible with roots in %q", s)
		}
	}
	return strategy, nil
}

// MustParseProvideStrategy is like ParseProvideStrategy but panics on error.
// Use with strategy strings that have already been validated at startup.
func MustParseProvideStrategy(s string) ProvideStrategy {
	strategy, err := ParseProvideStrategy(s)
	if err != nil {
		panic(err)
	}
	return strategy
}

// ValidateProvideConfig validates the Provide configuration according to DHT requirements.
func ValidateProvideConfig(cfg *Provide) error {
	// Validate Provide.Strategy

View on GitHub (pinned to 329838acdf)

Solutions

  1. Remove the +roots token so the strategy only uses DAG-walking bases, e.g. "pinned+unique" or "pinned+mfs+entities"
  2. If only root CIDs are wanted, drop +unique/+entities and keep "pinned+roots"
  3. Run `ipfs config Provide.Strategy "pinned+unique"` (or edit the config file) and restart the daemon

Example fix

// before
ipfs config Provide.Strategy 'pinned+roots+unique'
// after
ipfs config Provide.Strategy 'pinned+unique'
Defensive patterns

Strategy: validation

Validate before calling

func validStrategy(s string) bool {
	parts := strings.Split(s, "+")
	hasDedup := slices.ContainsFunc(parts, func(p string) bool { return p == "unique" || p == "entities" })
	if !hasDedup { return true }
	walksDAGs := slices.Contains(parts, "pinned") || slices.Contains(parts, "mfs")
	return walksDAGs && !slices.Contains(parts, "roots")
}

Type guard

func isDedupStrategy(s string) bool {
	st, err := config.ParseProvideStrategy(s)
	if err != nil { return false }
	return st&(config.ProvideStrategyUnique|config.ProvideStrategyEntities) != 0
}

Try / catch

strategy, err := config.ParseProvideStrategy(userInput)
if err != nil {
	return fmt.Errorf("invalid Provide.Strategy %q: %w", userInput, err)
}

Prevention

When it happens

Trigger: Calling config.ParseProvideStrategy, MustParseProvideStrategy, ValidateProvideConfig (via IPFS node init), or OnlineProviders with a strategy string that contains both a dedup modifier (+unique or +entities) and the +roots token, e.g. "pinned+roots+unique" or "roots+entities".

Common situations: Operators editing Provide.Strategy in the kubo config to reduce reprovide load add +unique to an existing "pinned+roots" strategy; migration scripts porting older strategy strings; confusion about which tokens are mutually exclusive.

Related errors


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