spacedriveapp/spacedrive · error · anyhow::Error
Failed to connect to {}: {}
Error message
Failed to connect to {}: {} What it means
endpoint.connect(node_id.into(), SYNC_ALPN) failed inside send_sync_request. Iroh must resolve the peer NodeId to reachable addresses (discovery, relays, cached direct addresses) and complete a QUIC/TLS handshake for the sync ALPN; the appended text is the underlying iroh error. It means the peer was unreachable at the transport level, not that sync logic failed.
Source
Thrown at core/src/service/network/protocol/sync/transport.rs:153
library_id = %request.library_id(),
"Sending sync request"
);
// Get endpoint
let endpoint = self
.endpoint
.as_ref()
.ok_or_else(|| anyhow::anyhow!("Network endpoint not initialized"))?;
// Connect with SYNC_ALPN
let conn = endpoint.connect(node_id.into(), SYNC_ALPN).await.map_err(|e| {
warn!(
device_uuid = %target_device,
node_id = %node_id,
error = %e,
"Failed to connect to device for sync request"
);
anyhow::anyhow!("Failed to connect to {}: {}", target_device, e)
})?;
// Open bidirectional stream
let (mut send, mut recv) = conn
.open_bi()
.await
.map_err(|e| anyhow::anyhow!("Failed to open bidirectional stream: {}", e))?;
// Serialize and send request
let req_bytes = serde_json::to_vec(&request)
.map_err(|e| anyhow::anyhow!("Failed to serialize sync request: {}", e))?;
let len = req_bytes.len() as u32;
send.write_all(&len.to_be_bytes())
.await
.map_err(|e| anyhow::anyhow!("Failed to send length: {}", e))?;
send.write_all(&req_bytes)
.awaitView on GitHub (pinned to 6dfeccf211)
Solutions
- Confirm the peer is online and paired (presence/heartbeat) before initiating sync
- Verify iroh relay and discovery configuration on both peers
- Retry with backoff - relay path establishment is often transient
- Re-pair the devices if the peer reset its identity (new NodeId)
- Ensure both devices run versions that agree on SYNC_ALPN
Example fix
// before
let resp = net.send_sync_request(device, req).await?;
// after
let resp = match net.send_sync_request(device, req.clone()).await {
Ok(resp) => resp,
Err(e) if is_connect_failure(&e) => {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
net.send_sync_request(device, req).await? // single retry
}
Err(e) => return Err(e),
}; Defensive patterns
Strategy: retry
Validate before calling
// Best-effort pre-check: skip peers not marked online
if !device_presence.is_online(device) {
return Ok(None);
}
net.send_sync_request(device, request).await?; Type guard
fn is_connect_failure(err: &anyhow::Error) -> bool {
err.to_string().starts_with("Failed to connect to")
} Try / catch
let mut attempt = 0;
loop {
match net.send_sync_request(device, request.clone()).await {
Ok(resp) => break Ok(resp),
Err(e) if is_connect_failure(&e) && attempt < 2 => {
attempt += 1;
tokio::time::sleep(std::time::Duration::from_secs(2u64 * attempt)).await;
}
Err(e) if is_connect_failure(&e) => {
mark_device_offline(device);
break Err(e);
}
Err(e) => break Err(e),
}
} Prevention
- Keep relay and discovery endpoints configured and reachable on all devices
- Check peer presence before initiating sync and skip offline peers
- Upgrade devices together so SYNC_ALPN stays identical
- Re-pair devices after any identity reset so NodeIds are current
When it happens
Trigger: Target device powered off or asleep; peer NodeId stale after an identity reset; no relay/discovery configured so the NodeId cannot be resolved to addresses; both peers behind restrictive NATs; ALPN mismatch because the peer runs a different spacedrive version.
Common situations: Syncing to a laptop that went to sleep; peer changed network leaving only stale address records; one device upgraded so SYNC_ALPN changed; air-gapped or relay-blocked networks.
Related errors
- Failed to connect to {}: {}
- Network endpoint not initialized
- Failed to open bidirectional stream: {}
- Failed to send length: {}
- Failed to send request: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/7dd7261e861cc4b8.
Report an issue: GitHub.