ipfs/kubo · warning · ErrNotConnected

not connected

Error message

not connected

What it means

ErrNotConnected is the sentinel error of the CoreAPI swarm interface, defined in core/coreiface/swarm.go. Swarm Disconnect returns it when you ask to disconnect from a peer that has no active connection — the node checks the libp2p host's Connectedness and short-circuits with this error if the peer is not in the Connected state.

Source

Thrown at core/coreiface/swarm.go:16

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

View on GitHub (pinned to 329838acdf)

Solutions

  1. Treat errors.Is(err, coreiface.ErrNotConnected) as success in disconnect/cleanup code — the desired end state (no connection) already holds
  2. Call api.Swarm().Peers(ctx) first to confirm the peer ID is present before disconnecting
  3. Verify the peer ID is correct (peer.Decode) and that the node is running and dialed the peer (Swarm().Connect) if a live connection was expected

Example fix

// before
err := api.Swarm().Disconnect(ctx, peerID)
if err != nil {
    return err // fails during cleanup when peer already gone
}

// after
err := api.Swarm().Disconnect(ctx, peerID)
if err != nil && !errors.Is(err, coreiface.ErrNotConnected) {
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

peers, err := api.Swarm().Peers(ctx)
if err != nil {
    return err
}
connected := false
for _, p := range peers {
    if p.ID() == targetID {
        connected = true
        break
    }
}
if connected {
    if err := api.Swarm().Disconnect(ctx, targetID); err != nil && !errors.Is(err, coreiface.ErrNotConnected) {
        return err
    }
}

Type guard

func isNotConnectedErr(err error) bool {
    return errors.Is(err, coreiface.ErrNotConnected)
}

Try / catch

err := api.Swarm().Disconnect(ctx, peerID)
switch {
case err == nil:
    // disconnected
case errors.Is(err, coreiface.ErrNotConnected):
    // already disconnected: treat as success in cleanup paths
default:
    return fmt.Errorf("disconnect %s: %w", peerID, err)
}

Prevention

When it happens

Trigger: Calling api.Swarm().Disconnect(ctx, peerID) (peer-ID form, core/coreapi/swarm.go:75) for a peer whose conn.Connectedness(id) != inet.Connected — the peer was never connected, already dropped the connection, or a peer ID is passed while the node is offline. Also returned by Disconnect generally when no matching live connection exists.

Common situations: Disconnecting in cleanup/shutdown code after the connection already timed out or was closed elsewhere; races where the remote peer disconnects between your check and call; typos in the peer ID so it never matched a real peer; calling before the daemon finished bootstrapping.

Related errors


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