ipfs/kubo · warning

fast-provide: %w

Error message

fast-provide: %w

What it means

ExecuteFastProvideRoot wraps a failure from the synchronous DHT provide of a root CID. When the 'wait' mode is selected, provideCIDSync blocks until the DHT client announces the CID; any underlying error (no DHT client, RPC failure, timeout) is wrapped as 'fast-provide: %w'. In async mode errors are only logged, so this error only surfaces from sync runs.

Source

Thrown at core/commands/cmdenv/env.go:172

	}

	// Check if strategy allows providing this content
	strategyStr := cfg.Provide.Strategy.WithDefault(config.DefaultProvideStrategy)
	strategy := config.MustParseProvideStrategy(strategyStr)
	shouldProvide := config.ShouldProvideForStrategy(strategy, isPinned, isPinnedRoot, isMFS)

	if !shouldProvide {
		log.Debugw("fast-provide-root: skipped", "reason", "strategy does not match content", "strategy", strategyStr, "pinned", isPinned, "pinnedRoot", isPinnedRoot, "mfs", isMFS)
		return nil
	}

	// Execute provide operation
	if wait {
		// Synchronous mode: block until provide completes, return error on failure
		log.Debugw("fast-provide-root: providing synchronously", "cid", rootCid)
		if err := provideCIDSync(ctx, ipfsNode.DHTClient, rootCid); err != nil {
			log.Warnw("fast-provide-root: sync provide failed", "cid", rootCid, "error", err)
			return fmt.Errorf("fast-provide: %w", err)
		}
		log.Debugw("fast-provide-root: sync provide completed", "cid", rootCid)
		return nil
	}

	// Asynchronous mode (default): fire-and-forget, don't block, always return nil.
	// Parent off the node's lifetime context (not context.Background) so the
	// goroutine cancels on daemon shutdown instead of potentially outliving
	// the node and touching a closed DHT client. The timeout still bounds
	// stuck DHT operations.
	log.Debugw("fast-provide-root: providing asynchronously", "cid", rootCid)
	go func() {
		ctx, cancel := context.WithTimeout(ipfsNode.Context(), config.DefaultFastProvideTimeout)
		defer cancel()
		if err := provideCIDSync(ctx, ipfsNode.DHTClient, rootCid); err != nil {
			log.Warnw("fast-provide-root: async provide failed", "cid", rootCid, "error", err)
		} else {
			log.Debugw("fast-provide-root: async provide completed", "cid", rootCid)

View on GitHub (pinned to 329838acdf)

Solutions

  1. Inspect the wrapped cause (%w) — fix the underlying DHT/routing error first
  2. Ensure the daemon has DHT/routing reachable (bootstrap peers, Swarm connectivity)
  3. Check Provide.Strategy / Provide.Enabled config if fast-provide shouldn't run
  4. Use async mode (omit wait) if blocking on provide is not required; failures then log as warnings
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check: node routing reachable
if cfg.Provide.Enabled == false {
    // skip fast-provide entirely
}

Try / catch

err := cmdenv.ExecuteFastProvideRoot(ctx, node, rootCid, true)
if err != nil {
    var cause error
    errors.As(err, &cause) // unwrap 'fast-provide: %w' to see the DHT error
    log.Warnf("sync provide failed: %v", cause)
}

Prevention

When it happens

Trigger: Running `ipfs pin add` / pinning with Provide.Strategy causing a fast-provide and --provide-wait (sync) when the DHT provide RPC fails: node offline, no bootstrap/DHT peers, provide worker error, or nil DHTClient.

Common situations: Nodes behind restrictive NAT/firewalls with no reachable DHT; Provide.Enabled or routing misconfiguration; tests without bootstrap peers trying sync provide.

Related errors


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