Skip to content
minip2p
Esc
↑↓navigate↵open⌘Jpreview
On this page

Rust troubleshooting

Diagnose Rust connection, stream, discovery, and event problems by symptom.

Start from the observable symptom. Building an endpoint fails with a BindError (or an EndpointOptionsError from a listen setter) naming the part that failed; methods on a running endpoint return minip2p::Error. Problems found while driving arrive as events.

Common problems

Symptom Likely cause What to do
listen_on or bind fails with an EndpointOptionsError (BindError::Options) A listen address is not listenable (/p2p, /p2p-circuit, a DNS host, or a transport whose Cargo feature is off), or the options conflict (no listen address, two QUIC addresses for one IP family) The variant names the address and what was expected; fix the options.
bind fails with BindError::Quic or BindError::Listen The platform refused a socket Match the error’s IoErrorKind: AddrInUse means another process holds the port, PermissionDenied a privileged port or sandbox.
PeerAddr fails to parse The address lacks a terminal /p2p/<peer-id> Copy the complete peer address.
connect returns ConnectTargetError The address list was empty, or its addresses name different peers Pass one peer’s complete addresses.
ConnectSettled fails with NoUsableRoute No candidate had a usable shape or transport, and no relay applied Use /udp/<port>/quic-v1 or /tcp/<port> and listen on that transport, or configure a relay.
A remote peer cannot connect to a printed address The address contains 0.0.0.0 or :: Advertise a real interface, public, or relay address.
A connection exists but an application protocol cannot open Protocol unregistered, or remote rejects negotiation Confirm matching protocol IDs and keep both peers driving. PeerReady is optional; it only enables early RemoteDoesNotSupport.
ProtocolNotRegistered The local endpoint never registered the protocol Add .protocol("/app/name/1.0.0") or call add_protocol.
RemoteDoesNotSupport The peer does not advertise the protocol version Register the same version on both peers.
An optional capability reports “not enabled” The Cargo feature exists, but the builder did not activate it Add the builder method listed in the feature matrix.
AutoNAT reports reachability but connect cannot relay Only an AutoNAT server was configured Add a Circuit Relay v2 server with .relay(...).
Hole punching fails UDP paths or observed addresses are unusable Keep the relay path, inspect HolePunchFailed, and keep both peers driving.
Pubsub receives no local copy Self-delivery is disabled Apply the local action directly and use pubsub for remote delivery.
Discovery rejects a beacon Discovery beacons must be signed Fix the publishing peer. allow_unsigned does not apply to discovery.
mDNS finds no peers mDNS is inactive, multicast is blocked, or peers do not share a link Activate mDNS on both peers and test on a multicast-capable network. Watch for EndpointEvent::MdnsFailed.

Event responses

Event Typical response
EndpointEvent::PeerReady Record advertised protocols, or open streams if you waited for Identify first.
EndpointEvent::StreamReady Attach the stream to its protocol handler.
EndpointEvent::StreamData Feed the bytes into the application’s decoder.
EndpointEvent::StreamRemoteWriteClosed Finish decoding and optionally close the local write side.
EndpointEvent::StreamWriteStopped Stop writing: the peer refused further bytes (QUIC STOP_SENDING). Keep reading until StreamClosed.
EndpointEvent::Error Record the structured context and decide whether to retry.
EndpointEvent::MdnsFailed Log the MdnsError (operation, IoErrorKind, interface). mDNS keeps retrying and emits MdnsRecovered once it works again.
RelayServerEvent::AddrsRejected Fix the listener or confirmed address it names. The previously accepted addresses stay in effect until AddrsRestored.
NatEvent::PathEstablished Begin traffic with the ordinary stream methods.
NatEvent::PathUpgraded Update path state. Existing peer operations keep working.
EndpointEvent::ConnectSettled with ConnectOutcome::Failed Inspect the failure, correct the candidates or infrastructure, and retry.
GossipsubEvent::OutboundFailure Retry only if the application requires it.
DiscoveryEvent::DialFailed Keep discovery running. Backoff controls later attempts.

Debug in order

  1. Confirm that both endpoints keep calling wait or poll. Each call drives only its own endpoint, so blocking on one endpoint can delay others sharing the same thread.
  2. Log the complete peer address and local peer ID.
  3. Distinguish an authenticated connection from PeerReady (Identify).
  4. Confirm both the Cargo feature and its builder method.
  5. Match the capability’s EndpointEvent variant (Nat, Gossipsub, Discovery, RelayServer, MdnsFailed) from wait or poll, and check durable state with the snapshot getters (path, reachability, active_reservation, known_peers).

For the complete capability map, see the feature matrix.

Last updated on October 22, 2026

Was this page helpful?