ipfs/kubo · critical

cannot create libp2p gateway: node PeerHost is nil (this sho

Error message

cannot create libp2p gateway: node PeerHost is nil (this should not happen and likely indicates an FX dependency injection issue or race condition)

What it means

The daemon tries to serve the trustless gateway over libp2p using p2phttp.Host, which requires node.PeerHost (the libp2p host) to be initialized. This error means the FX dependency-injection graph did not populate PeerHost before serveTrustlessGatewayOverLibp2p ran, or a race let the gateway setup proceed before node construction finished. It indicates a daemon startup bug rather than a user configuration mistake.

Source

Thrown at cmd/ipfs/kubo/daemon.go:1211

	if !cfg.Experimental.GatewayOverLibp2p {
		errCh := make(chan error)
		close(errCh)
		return errCh, nil
	}

	opts := []corehttp.ServeOption{
		corehttp.MetricsCollectionOption("libp2p-gateway"),
		corehttp.Libp2pGatewayOption(),
		corehttp.VersionOption(),
	}

	handler, err := corehttp.MakeHandler(node, nil, opts...)
	if err != nil {
		return nil, err
	}

	if node.PeerHost == nil {
		return nil, fmt.Errorf("cannot create libp2p gateway: node PeerHost is nil (this should not happen and likely indicates an FX dependency injection issue or race condition)")
	}

	h := p2phttp.Host{
		StreamHost: node.PeerHost,
	}

	h.WellKnownHandler.AddProtocolMeta(gatewayProtocolID, p2phttp.ProtocolMeta{Path: "/"})
	h.ServeMux = http.NewServeMux()
	h.ServeMux.Handle("/", handler)

	errc := make(chan error, 1)
	go func() {
		errc <- h.Serve()
		close(errc)
	}()

	context.AfterFunc(node.Context(), func() {
		h.Close()

View on GitHub (pinned to 329838acdf)

Solutions

  1. Verify the daemon was built from unmodified sources and update to the latest kubo release, then retry
  2. Report/log the full startup output: this is an internal invariant violation and should be filed as a bug at github.com/ipfs/kubo/issues
  3. If building from source, check that the FX graph still constructs a libp2p host and that serveTrustlessGatewayOverLibp2p only runs after node construction completes
  4. As a workaround, disable the libp2p trustless gateway so the code path is not taken

Example fix

// before
if node.PeerHost == nil {
	return nil, fmt.Errorf("cannot create libp2p gateway: node PeerHost is nil ...")
}
// after (defensive ordering at call site)
if node.PeerHost == nil {
	return nil, fmt.Errorf("cannot create libp2p gateway: node PeerHost is nil (fx dependency issue): %w", errNodeNotReady)
}
Defensive patterns

Strategy: type-guard

Validate before calling

if node == nil || node.PeerHost == nil {
	// skip libp2p gateway or fail fast before calling p2phttp setup
}

Type guard

func peerHostReady(n *core.IpfsNode) bool { return n != nil && n.PeerHost != nil }

Try / catch

gh, err := serveTrustlessGatewayOverLibp2p(node, opts...)
if err != nil {
	if strings.Contains(err.Error(), "PeerHost is nil") {
		// fall back to HTTP-only gateway or abort startup with a clear diagnostic
	}
	return err
}

Prevention

When it happens

Trigger: Running the daemon with the libp2p gateway enabled (ipfs daemon) while the FX DI graph fails or races so node.PeerHost remains nil when serveTrustlessGatewayOverLibp2p executes; typically only reproducible with internal startup-order regressions or plugin/host injection failures.

Common situations: Developers modifying core node construction or the FX wiring in kubo; running a patched/custom build where the libp2p host construction was removed or deferred; rarely, races on very slow startup paths.

Related errors


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