ipfs/kubo · warning · ErrConnNotFound

conn not found

Error message

conn not found

What it means

ErrConnNotFound is a sentinel error of the CoreAPI swarm interface, defined in core/coreiface/swarm.go. Disconnect returns it when the multiaddr form is used (core/coreapi/swarm.go:89): the node enumerated its live connections and none of them is over the given address, so there is nothing to close.

Solutions

  1. Check api.Swarm().Peers(ctx) and disconnect using the exact Address() strings from its output, refreshed at call time
  2. Prefer the peer-ID form: Disconnect(ctx, peer.ID) — it closes the connection regardless of which address it uses (returning ErrNotConnected instead if already gone)
  3. Accept errors.Is(err, coreiface.ErrConnNotFound) as a no-op success in cleanup paths

Example fix

// before
addrs, _ := api.Swarm().Peers(ctx) // stale snapshot
_ = addrs[0].Address().String()     // connection since dropped
err := api.Swarm().Disconnect(ctx, staleAddr) // ErrConnNotFound

// after
peers, _ := api.Swarm().Peers(ctx)
for _, p := range peers {
    if p.ID() == targetID {
        err := api.Swarm().Disconnect(ctx, p.ID())
        if err != nil && !errors.Is(err, coreiface.ErrConnNotFound) {
            return err
        }
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

peers, err := api.Swarm().Peers(ctx)
if err != nil {
    return err
}
found := false
for _, p := range peers {
    if p.Address().Equal(targetAddr) {
        found = true
        break
    }
}
if !found {
    return nil // nothing to disconnect
}
err = api.Swarm().Disconnect(ctx, targetAddr)

Type guard

func isConnNotFoundErr(err error) bool {
    return errors.Is(err, coreiface.ErrConnNotFound)
}

Try / catch

err := api.Swarm().Disconnect(ctx, addr)
switch {
case err == nil:
    // connection closed
case errors.Is(err, coreiface.ErrConnNotFound):
    // no live connection on that address: treat as no-op
default:
    return fmt.Errorf("disconnect %s: %w", addr, err)
}

Prevention

When it happens

Trigger: Calling api.Swarm().Disconnect(ctx, addr) with a multiaddr that does not match any active connection: the connection dropped already (so Peerstore keeps the addr but no conn exists), a stale relay/circuit address, a DNS address that resolved differently from the dialed form, or a wrong port/scheme typo.

Common situations: Disconnecting a specific connection after a relay circuit was recycled; peers that connected via a different address than advertised (e.g. AutoTLS *.libp2p.direct vs raw TCP); reconnect-and-disconnect races in tests; hardcoding addresses from an earlier Peers() snapshot.

Related errors


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

Appendix: source

Thrown at core/coreiface/swarm.go:17

package iface

import (
	"context"
	"errors"
	"time"

	"github.com/libp2p/go-libp2p/core/network"
	"github.com/libp2p/go-libp2p/core/peer"
	"github.com/libp2p/go-libp2p/core/protocol"

	ma "github.com/multiformats/go-multiaddr"
)

var (
	ErrNotConnected = errors.New("not connected")
	ErrConnNotFound = errors.New("conn not found")
)

// ConnectionInfo contains information about a peer
type ConnectionInfo interface {
	// ID returns PeerID
	ID() peer.ID

	// Address returns the multiaddress via which we are connected with the peer
	Address() ma.Multiaddr

	// Direction returns which way the connection was established
	Direction() network.Direction

	// Latency returns last known round trip time to the peer
	Latency() (time.Duration, error)

	// Streams returns list of streams established with the peer
	Streams() ([]protocol.ID, error)

View on GitHub (pinned to 329838acdf)