spacedriveapp/spacedrive · error · anyhow::Error
Failed to read response: {}
Error message
Failed to read response: {} What it means
After reading the 4-byte length, reading the announced response body failed. The stream ended before resp_len bytes arrived (truncated response) or the connection dropped mid-body - the peer started a response it never finished.
Source
Thrown at core/src/service/network/protocol/sync/transport.rs:193
send.finish()
.map_err(|e| anyhow::anyhow!("Failed to finish stream: {}", e))?;
debug!("Sync request sent, waiting for response...");
// Read response with timeout
let result = timeout(Duration::from_secs(60), async {
let mut len_buf = [0u8; 4];
recv.read_exact(&mut len_buf).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))?;View on GitHub (pinned to 6dfeccf211)
Solutions
- Retry the request - truncation is usually transient
- If reproducible, log resp_len and peer-side sent-byte counts to find the framing bug
- Stream large responses in chunks instead of one length-prefixed blob
- Sanity-check resp_len before allocating the buffer
Example fix
// before
let mut resp_buf = vec![0u8; resp_len];
// after
const MAX_RESPONSE_BYTES: usize = 256 * 1024 * 1024;
if resp_len > MAX_RESPONSE_BYTES {
anyhow::bail!("implausible response length {}", resp_len);
}
let mut resp_buf = vec![0u8; resp_len]; Defensive patterns
Strategy: retry
Validate before calling
// Before trusting the length prefix (guards huge allocations from corrupt data)
const MAX_RESPONSE_BYTES: usize = 256 * 1024 * 1024;
if resp_len > MAX_RESPONSE_BYTES {
return Err(anyhow::anyhow!("implausible response length {}", resp_len));
} Try / catch
Err(e) if e.to_string().contains("Failed to read response") => {
// truncated response: retry once; if reproducible, compare resp_len with peer-side byte counts
retry_request_on_fresh_connection(device, request).await
} Prevention
- Validate resp_len before allocating the receive buffer
- Retry once; mid-body truncation is usually transient
- For large libraries, prefer chunked streaming responses over single blobs
When it happens
Trigger: Peer killed while serializing or sending a large response; peer wrote fewer bytes than its length prefix claimed (framing bug); network cutoff mid-transfer.
Common situations: First sync of a large library producing a big diff response; peer OOM during response construction; flaky link.
Related errors
- Failed to read response length: {}
- Failed to open bidirectional stream: {}
- Failed to send length: {}
- Failed to send request: {}
- Failed to open stream: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/2e33b9459187a7bc.
Report an issue: GitHub.