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 tokio timeout(Duration::from_secs(60)) wrapping the entire response read elapsed. The peer accepted the connection and the request but did not deliver a complete response within 60 seconds - slow response generation on the peer, a stuck handler, or a stalled network path.

Source

Thrown at core/src/service/network/protocol/sync/transport.rs:202

				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

  1. Raise the timeout or make it adaptive to library size
  2. Have the peer emit progress or keepalive bytes so the reader does not time out during long computations
  3. Profile the peer handler stage that is slow
  4. Retry once - transient stalls are common

Example fix

// before
let result = timeout(Duration::from_secs(60), async { /* read */ }).await;

// after
let budget = Duration::from_secs(60 + (library_size / 10_000).max(0));
let result = timeout(budget, async { /* read */ }).await;
Defensive patterns

Strategy: retry

Type guard

fn is_sync_timeout(err: &anyhow::Error) -> bool {
    err.to_string().contains("timed out after 60s")
}

Try / catch

match net.send_sync_request(device, request).await {
    Ok(resp) => { /* ... */ }
    Err(e) if is_sync_timeout(&e) => {
        // peer alive but slow: retry with a longer budget before giving up
        tokio::time::sleep(std::time::Duration::from_secs(5)).await;
        net.send_sync_request(device, request).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Peer computing an expensive diff over a large library; peer handler deadlocked (for example lock contention); relay path with extreme latency; peer CPU saturated by another job.

Common situations: Initial sync of large libraries; low-power devices (phones, SBCs); peer busy with indexing or backups.

Understand the failure class

Related errors


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