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 peerView on GitHub (pinned to 329838acdf)
Solutions
- Treat errors.Is(err, coreiface.ErrNotConnected) as success in disconnect/cleanup code — the desired end state (no connection) already holds
- Call api.Swarm().Peers(ctx) first to confirm the peer ID is present before disconnecting
- 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
- Idempotent-disconnect habit: always tolerate ErrNotConnected in teardown code
- Confirm connectivity with Swarm().Peers before a Disconnect you expect to succeed
- Re-check peer IDs with peer.Decode before calling — a malformed ID never matches a peer
- Remember connections can drop asynchronously; the error may reflect a race, not a bug
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
- conn not found
- no local swarm address for migration node
- could not connect to migration peer %q: %s
- serveHTTPApi: %w
- serveHTTPGateway: manet.Listen(%s) failed: %s
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/348b65b425349ee0.
Report an issue: GitHub.