ipfs/kubo · error

could not perform version check due to missing or incompatib

Error message

could not perform version check due to missing or incompatible DHT configuration

What it means

DetectNewKuboVersion relies on the Amino DHT client (FullRT) retaining peer information about previously seen swarm peers. When the node claims to have an active DHT client (nd.HasActiveDHTClient()) but nd.DHTClient is not a *fullrt.FullRT, the code cannot enumerate seen peers and returns this error. It signals an unexpected/incompatible DHT implementation at runtime.

Source

Thrown at core/commands/version.go:261

		if peerVersion.GreaterThan(greatestVersionSeen) {
			greatestVersionSeen = peerVersion
		}
	}

	processPeerstoreEntry := func(id peer.ID) {
		if v, err := nd.Peerstore.Get(id, "AgentVersion"); err == nil {
			recordPeerVersion(v.(string))
		} else if errors.Is(err, pstore.ErrNotFound) { // ignore noop
		} else { // a bug, usually.
			log.Errorw("failed to get agent version from peerstore", "error", err)
		}
	}

	// Amino DHT client keeps information about previously seen peers
	if nd.HasActiveDHTClient() && nd.DHTClient != nd.DHT {
		client, ok := nd.DHTClient.(*fullrt.FullRT)
		if !ok {
			return VersionCheckOutput{}, errors.New("could not perform version check due to missing or incompatible DHT configuration")
		}
		for _, p := range client.Stat() {
			processPeerstoreEntry(p)
		}
	} else if nd.DHT != nil && nd.DHT.WAN != nil {
		for _, pi := range nd.DHT.WAN.RoutingTable().GetPeerInfos() {
			processPeerstoreEntry(pi.Id)
		}
	} else if nd.DHT != nil && nd.DHT.LAN != nil {
		for _, pi := range nd.DHT.LAN.RoutingTable().GetPeerInfos() {
			processPeerstoreEntry(pi.Id)
		}
	} else {
		return VersionCheckOutput{}, errors.New("could not perform version check due to missing or incompatible DHT configuration")
	}

	if minPercent < 1 || minPercent > 100 {
		if minPercent == 0 {

View on GitHub (pinned to 329838acdf)

Solutions

  1. Run stock Kubo routing configuration (no custom DHT replacement) when using 'ipfs version check'
  2. Update to a matching official kubo release so nd.DHTClient is the standard FullRT client
  3. If you maintain a fork/plugin that swaps the DHT, either provide a FullRT-compatible client or skip the swarm version check
  4. Check config for experimental routing flags that alter DHT setup and reset them to defaults
Defensive patterns

Strategy: fallback

Validate before calling

if nd.HasActiveDHTClient() {
    if _, ok := nd.DHTClient.(*fullrt.FullRT); !ok {
        return errors.New("swarm version check requires the standard FullRT DHT client")
    }
}

Type guard

func isFullRT(v interface{}) bool {
    _, ok := v.(*fullrt.FullRT)
    return ok
}

Try / catch

out, err := DetectNewKuboVersion(nd, pct)
if err != nil && strings.Contains(err.Error(), "missing or incompatible DHT configuration") {
    log.Warnf("swarm version check unavailable: %v", err)
    return VersionCheckOutput{}, nil
}
return out, err

Prevention

When it happens

Trigger: 'ipfs version check' or the daemon's periodic swarm version check on a node where DHTClient is set but is not a FullRT instance — e.g. a custom or mocked DHT client, or an internal build where the client type changed.

Common situations: Running with experimental/custom routing configurations that swap the DHT implementation; plugin or fork code replacing the DHT client; version skew between kubo and its go-libp2p-kad-dht dependency after a hand-rolled dependency bump.

Related errors


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