{"record":{"id":"42f89d891bd9e73c","repo":"ipfs/kubo","slug":"cannot-create-libp2p-gateway-node-peerhost-is-nil","errorCode":null,"errorMessage":"cannot create libp2p gateway: node PeerHost is nil (this should not happen and likely indicates an FX dependency injection issue or race condition)","messagePattern":"cannot create libp2p gateway: node PeerHost is nil \\(this should not happen and likely indicates an FX dependency injection issue or race condition\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cmd/ipfs/kubo/daemon.go","lineNumber":1211,"sourceCode":"\tif !cfg.Experimental.GatewayOverLibp2p {\n\t\terrCh := make(chan error)\n\t\tclose(errCh)\n\t\treturn errCh, nil\n\t}\n\n\topts := []corehttp.ServeOption{\n\t\tcorehttp.MetricsCollectionOption(\"libp2p-gateway\"),\n\t\tcorehttp.Libp2pGatewayOption(),\n\t\tcorehttp.VersionOption(),\n\t}\n\n\thandler, err := corehttp.MakeHandler(node, nil, opts...)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif node.PeerHost == nil {\n\t\treturn 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)\")\n\t}\n\n\th := p2phttp.Host{\n\t\tStreamHost: node.PeerHost,\n\t}\n\n\th.WellKnownHandler.AddProtocolMeta(gatewayProtocolID, p2phttp.ProtocolMeta{Path: \"/\"})\n\th.ServeMux = http.NewServeMux()\n\th.ServeMux.Handle(\"/\", handler)\n\n\terrc := make(chan error, 1)\n\tgo func() {\n\t\terrc <- h.Serve()\n\t\tclose(errc)\n\t}()\n\n\tcontext.AfterFunc(node.Context(), func() {\n\t\th.Close()","sourceCodeStart":1193,"sourceCodeEnd":1229,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/cmd/ipfs/kubo/daemon.go#L1193-L1229","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the daemon was built from unmodified sources and update to the latest kubo release, then retry","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","If building from source, check that the FX graph still constructs a libp2p host and that serveTrustlessGatewayOverLibp2p only runs after node construction completes","As a workaround, disable the libp2p trustless gateway so the code path is not taken"],"exampleFix":"// before\nif node.PeerHost == nil {\n\treturn nil, fmt.Errorf(\"cannot create libp2p gateway: node PeerHost is nil ...\")\n}\n// after (defensive ordering at call site)\nif node.PeerHost == nil {\n\treturn nil, fmt.Errorf(\"cannot create libp2p gateway: node PeerHost is nil (fx dependency issue): %w\", errNodeNotReady)\n}","handlingStrategy":"type-guard","validationCode":"if node == nil || node.PeerHost == nil {\n\t// skip libp2p gateway or fail fast before calling p2phttp setup\n}","typeGuard":"func peerHostReady(n *core.IpfsNode) bool { return n != nil && n.PeerHost != nil }","tryCatchPattern":"gh, err := serveTrustlessGatewayOverLibp2p(node, opts...)\nif err != nil {\n\tif strings.Contains(err.Error(), \"PeerHost is nil\") {\n\t\t// fall back to HTTP-only gateway or abort startup with a clear diagnostic\n\t}\n\treturn err\n}","preventionTips":["Ensure serveTrustlessGatewayOverLibp2p only runs after FX fully populates the node (post-construction hook, not during)","Never mutate or bypass the FX graph that constructs the libp2p host in custom builds","Keep kubo updated; file a bug if this fires on stock builds — it is an internal invariant violation"],"tags":["go","daemon","dependency-injection","startup"],"backgroundTag":"nil-dependency-injection","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}