spacedriveapp/spacedrive · error · anyhow::Error

Failed to connect to {}: {}

Error message

Failed to connect to {}: {}

What it means

endpoint.connect(node_id, SYNC_ALPN) failed on the cache-miss path of send_sync_message (transports/sync.rs). Iroh could not resolve or reach the peer NodeId for the sync ALPN within the handshake; the appended text is the underlying iroh error. The failure happens before any connection is cached.

Source

Thrown at core/src/service/network/transports/sync.rs:102

		// Create new connection only if cache miss
		let conn = if let Some(conn) = conn {
			conn
		} else {
			tracing::debug!(
				device_uuid = %target_device,
				node_id = %node_id,
				"Creating new connection (cache miss)"
			);

			let new_conn = endpoint.connect(node_id, SYNC_ALPN).await.map_err(|e| {
				warn!(
					device_uuid = %target_device,
					node_id = %node_id,
					error = %e,
					"Failed to connect to device for sync"
				);
				anyhow::anyhow!("Failed to connect to {}: {}", target_device, e)
			})?;

			// Add to cache
			{
				let mut connections = active_connections.write().await;
				connections.insert(cache_key, new_conn.clone());
			}

			// Track outbound connection so we can receive incoming streams on it
			if let Some(cmd_sender) = self.command_sender() {
				use crate::service::network::core::event_loop::EventLoopCommand;
				let _ = cmd_sender.send(EventLoopCommand::TrackOutboundConnection {
					node_id,
					conn: new_conn.clone(),
				});
			}

			new_conn

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Check device presence before sending and skip offline peers
  2. Verify relay and discovery configuration on both sides
  3. Retry with backoff; transient relay failures clear quickly
  4. Re-pair if the peer generated a new NodeId
  5. Align spacedrive versions so SYNC_ALPN matches
Defensive patterns

Strategy: retry

Validate before calling

// Best-effort pre-check before the cache-miss connect
if !device_presence.is_online(device) {
    return Ok(());
}
net.send_sync_message(device, message).await?;

Type guard

fn is_connect_failure(err: &anyhow::Error) -> bool {
    err.to_string().starts_with("Failed to connect to")
}

Try / catch

match net.send_sync_message(device, msg).await {
    Ok(()) => {}
    Err(e) if is_connect_failure(&e) => {
        // transient reachability: bounded backoff retry, then mark device offline
        mark_device_offline(device);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Peer offline or asleep; NodeId stale after peer identity reset; discovery/relay unconfigured or unreachable; NAT traversal failing on both sides; ALPN mismatch from version skew.

Common situations: Sync fan-out to devices that went offline; network changes invalidating direct addresses; one-sided upgrades changing SYNC_ALPN.

Related errors


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/f5e1bfe03e8950c2. Report an issue: GitHub.