spacedriveapp/spacedrive · error · anyhow::Error
Sync request timed out after 60s - peer {} not responding
Error message
Sync request timed out after 60s - peer {} not responding What it means
The 60-second tokio timeout wrapping the response read expired: the peer neither sent a response nor closed the stream. The transport connection is fine, but the peer's sync handler is stuck (blocked on a lock or a very long database operation) or traffic is black-holed by a NAT or relay path. Note the timeout wraps the whole read, so a very slow large response also trips it.
Source
Thrown at core/src/service/network/transports/sync.rs:299
.await
.map_err(|e| anyhow::anyhow!("Failed to read response length: {}", e))?;
let resp_len = u32::from_be_bytes(len_buf) as usize;
debug!("Receiving sync response of {} bytes", resp_len);
let mut resp_buf = vec![0u8; resp_len];
recv.read_exact(&mut resp_buf)
.await
.map_err(|e| anyhow::anyhow!("Failed to read response: {}", e))?;
Ok::<_, anyhow::Error>(resp_buf)
})
.await;
let resp_buf = match result {
Ok(Ok(buf)) => buf,
Ok(Err(e)) => return Err(e),
Err(_) => {
return Err(anyhow::anyhow!(
"Sync request timed out after 60s - peer {} not responding",
target_device
))
}
};
// Deserialize response
let response: SyncMessage = serde_json::from_slice(&resp_buf)
.map_err(|e| anyhow::anyhow!("Failed to deserialize sync response: {}", e))?;
debug!(
device_uuid = %target_device,
response_type = ?std::mem::discriminant(&response),
"Received sync response"
);
Ok(response)
}View on GitHub (pinned to 6dfeccf211)
Solutions
- Check peer health and its logs: a silently unresponsive peer is usually stuck, not slow
- Retry with backoff; a second consecutive timeout on an idle peer confirms it is unavailable
- For bulk sync, raise the timeout or move to a streamed job protocol so progress is visible instead of one 60s-capped response
- Keep individual request payloads small so responses complete well under the cap
Defensive patterns
Strategy: retry
Validate before calling
// Check peer responsiveness before committing to a long exchange
if !transport.is_device_reachable(target_device).await {
return Ok(None);
} Try / catch
match transport.send_sync_request(target, request).await {
Err(e) if e.to_string().contains("timed out after 60s") => {
// peer hung: back off, verify peer health, retry a bounded number of times
}
other => other,
} Prevention
- Keep request payloads small so responses finish well under the 60s cap
- Move bulk sync to a streamed or job-based protocol with visible progress
- Track consecutive timeouts per peer and quarantine unresponsive peers
When it happens
Trigger: Peer handler deadlocks on a contended lock while processing the request; initial sync of a huge dataset where the peer needs more than 60s to assemble the response; a relay or NAT path silently dropping packets so no data or FIN ever arrives.
Common situations: First sync after pairing two large libraries; peers on mobile or unstable networks; a peer suspended by the OS while holding the sync handler.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Sync request timed out after 60s - peer {} not responding
- No paired devices found. Pair a device first with: sd networ
- Remote device {} is not online
- Network endpoint not initialized
- Failed to connect to {}: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/003ce1cec015190e.
Report an issue: GitHub.