{"record":{"id":"a7aec96b85ad692e","repo":"ipfs/kubo","slug":"getclosestpeers-not-supported-wan-dht-is-not-avai","errorCode":null,"errorMessage":"GetClosestPeers not supported: WAN DHT is not available","messagePattern":"GetClosestPeers not supported: WAN DHT is not available","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/corehttp/routing.go","lineNumber":123,"sourceCode":"\t// Per the spec, if the peer ID is empty, we should use self.\n\tif key == cid.Undef {\n\t\treturn nil, errors.New(\"GetClosestPeers key is undefined\")\n\t}\n\n\tkeyStr := string(key.Hash())\n\tvar peers []peer.ID\n\tvar err error\n\n\tif r.n.DHTClient == nil {\n\t\treturn nil, fmt.Errorf(\"GetClosestPeers not supported: DHT is not available\")\n\t}\n\n\tswitch dhtClient := r.n.DHTClient.(type) {\n\tcase *dual.DHT:\n\t\t// Only use WAN DHT for public HTTP Routing API.\n\t\t// LAN DHT contains private network peers that should not be exposed publicly.\n\t\tif dhtClient.WAN == nil {\n\t\t\treturn nil, fmt.Errorf(\"GetClosestPeers not supported: WAN DHT is not available\")\n\t\t}\n\t\tpeers, err = dhtClient.WAN.GetClosestPeers(ctx, keyStr)\n\tcase *fullrt.FullRT:\n\t\tpeers, err = dhtClient.GetClosestPeers(ctx, keyStr)\n\tcase *dht.IpfsDHT:\n\t\tpeers, err = dhtClient.GetClosestPeers(ctx, keyStr)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"GetClosestPeers not supported for DHT type %T\", r.n.DHTClient)\n\t}\n\n\t// A lookup cut short by the deadline returns the closest peers found so far\n\t// along with the context error. The HTTP routing server caps every request\n\t// (server.DefaultRoutingTimeout), so on a slow query this is the difference\n\t// between a useful answer and a 500.\n\tif err != nil && len(peers) == 0 {\n\t\treturn nil, err\n\t}\n","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/corehttp/routing.go#L105-L141","documentation":"This error comes from the HTTP Routing API's GetClosestPeers handler in Kubo. When a node's DHT client is a dual.DHT (separate WAN and LAN DHT instances), the public HTTP routing API only delegates to the WAN DHT, since LAN DHT holds private-network peers that must not be exposed over a public API. If the WAN half of the dual DHT is nil (never initialized), the endpoint cannot serve the request and returns this error instead.","triggerScenarios":"Calling the HTTP Routing API (`routing/v1`) GetClosestPeers endpoint on a node whose DHTClient is *dual.DHT with dhtClient.WAN == nil, i.e. the node was configured without a WAN/public DHT (e.g. `Routing.Type` not creating a public DHT, or running in a private-network/LAN-only setup).","commonSituations":"Operators running nodes in private networks (Libp2p private networks with a swarm key) where the WAN DHT is intentionally disabled; misconfigured Routing.Type (e.g. 'none' or custom) leading to a dual DHT with no WAN half; exposing the routing API on a node that was never meant to be a public routing provider.","solutions":["Ensure the node is configured to run a public (WAN) DHT, e.g. set `ipfs config Routing.Type dhtclient` (or `dhtserver`) and restart the daemon so the dual DHT initializes its WAN instance.","If the node must stay in a private network, do not expose the public HTTP Routing API from it; point clients at a node that has a WAN DHT.","Verify at runtime that the node has a WAN DHT before serving routing requests, e.g. by checking the node's routing configuration or by catching this error and returning a clearer 4xx/5xx to the API caller."],"exampleFix":"// Node configuration (shell), ensure WAN DHT exists:\n// before (private/none routing)\nipfs config Routing.Type none\n// after\nipfs config Routing.Type dhtclient\n\n// Client side, guard the call:\npeers, err := rt.GetClosestPeers(ctx, key)\nif err != nil && strings.Contains(err.Error(), \"WAN DHT is not available\") {\n    // fall back to a different routing node\n}","handlingStrategy":"fallback","validationCode":"// Confirm the node runs a public DHT before calling the endpoint:\n// ipfs config Routing.Type   -> expect 'dhtclient' or 'dhtserver'\n// (a nil WAN DHT usually means private-network or routing=none setups)","typeGuard":"func wanDHTAvailable(n *core.IpfsNode) bool {\n    d, ok := n.DHTClient.(*dual.DHT)\n    return ok && d.WAN != nil\n}","tryCatchPattern":"peers, err := rt.GetClosestPeers(ctx, key)\nif err != nil {\n    if strings.Contains(err.Error(), \"WAN DHT is not available\") {\n        peers, err = fallbackRouter.GetClosestPeers(ctx, key)\n    }\n    if err != nil { return err }\n}","preventionTips":["Run the node with Routing.Type dhtclient/dhtserver so the WAN DHT is initialized","Do not expose the public HTTP Routing API on private-network (swarm-key) nodes","Health-check the routing endpoint at startup and fail over to another routing provider"],"tags":["dht","routing","http-api","kubo"],"backgroundTag":"dht-wan-not-available","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"}