ipfs/kubo · error

ErrNotDHT

ErrNotDHT

Error message

routing service is not a DHT

What it means

ErrNotDHT is returned by deprecated `ipfs dht` commands when the node's routing service is not a DHT-based router. Kubo can be configured with alternative routing (e.g. delegated HTTP routers, or no DHT), in which case the dht-specific subcommands have nothing to talk to. It is a guard, not a bug, and the same condition is checked as `nd.HasActiveDHTClient()` or `nd.DHT == nil`.

Source

Thrown at core/commands/dht.go:15

package commands

import (
	"context"
	"errors"
	"fmt"
	"io"

	cmds "github.com/ipfs/go-ipfs-cmds"
	"github.com/ipfs/kubo/core/commands/cmdenv"
	peer "github.com/libp2p/go-libp2p/core/peer"
	routing "github.com/libp2p/go-libp2p/core/routing"
)

var ErrNotDHT = errors.New("routing service is not a DHT")

var DhtCmd = &cmds.Command{
	Status: cmds.Deprecated,
	Helptext: cmds.HelpText{
		Tagline:          "Issue commands directly through the DHT.",
		ShortDescription: ``,
	},

	Subcommands: map[string]*cmds.Command{
		"query":     queryDhtCmd,
		"findprovs": RemovedDHTCmd,
		"findpeer":  RemovedDHTCmd,
		"get":       RemovedDHTCmd,
		"put":       RemovedDHTCmd,
		"provide":   RemovedDHTCmd,
	},
}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Check `ipfs config Routing.Type` and set it to a DHT-backed value (e.g. 'auto'/'dhtclient'/'dhtserver') if DHT access is wanted
  2. Use the `ipfs routing` command family instead of the deprecated `ipfs dht` commands
  3. Verify the daemon actually started with an active DHT client (`ipfs stats dht` or `ipfs routing stat`)

Example fix

// before
ipfs dht findprovs <cid>   // -> routing service is not a DHT
// after
ipfs routing findprovs <cid>
Defensive patterns

Strategy: fallback

Validate before calling

cfg, _ := ipfs.Config()
if cfg.Routing.Type != "dhtclient" && cfg.Routing.Type != "dhtserver" && cfg.Routing.Type != "auto" { /* fall back to ipfs routing commands */ }

Type guard

// client-side: check DHT presence before invoking
if !node.HasActiveDHTClient() { return ErrNotDHT }

Try / catch

out, err := runCmd("ipfs dht findprovs", cid)
if errors.Is(err, ErrNotDHT) || strings.Contains(err.Error(), "routing service is not a DHT") {
    out, err = runCmd("ipfs routing findprovs", cid)
}

Prevention

When it happens

Trigger: Running `ipfs dht findprovs`, `ipfs dht query` or other dht subcommands on a node where Routing.Type is configured to a non-DHT router (e.g. 'delegated'/'custom') or where no DHT client is active (`!nd.HasActiveDHTClient()`), or `ipfs dht stat` when `nd.DHT` is nil.

Common situations: Nodes configured for delegated/no-DHT routing (common for hosted/lightweight nodes); running dht commands against a client-less daemon; old scripts that still use the deprecated `ipfs dht` command tree after switching routing config.

Related errors


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