spacedriveapp/spacedrive · error · anyhow::Error
Failed to open bidirectional stream: {}
Error message
Failed to open bidirectional stream: {} What it means
After a successful connect, conn.open_bi() failed in send_sync_request. On a QUIC connection this happens when the connection is lost or stopped between connect and stream creation, when the peer's bidirectional stream limit is exhausted, or when the peer's accept loop has stopped (crashed or shutting down).
Source
Thrown at core/src/service/network/protocol/sync/transport.rs:160
.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)
.await
.map_err(|e| anyhow::anyhow!("Failed to send request: {}", e))?;
// Properly close send stream
send.finish()
.map_err(|e| anyhow::anyhow!("Failed to finish stream: {}", e))?;
debug!("Sync request sent, waiting for response...");View on GitHub (pinned to 6dfeccf211)
Solutions
- Drop the connection and retry the request once on a fresh connection
- Check the peer's logs for a crashed or exited sync accept loop
- Bound the number of concurrent in-flight sync requests per peer
- Confirm the peer accepts bidirectional streams for SYNC_ALPN
Defensive patterns
Strategy: retry
Try / catch
match net.send_sync_request(device, request.clone()).await {
Ok(resp) => { /* ... */ }
Err(e) if e.to_string().contains("Failed to open bidirectional stream") => {
// connection-level failure: drop conn, reconnect once, retry
retry_once_with_fresh_connection(device, request).await
}
Err(e) => Err(e),
} Prevention
- Bound concurrent sync requests per peer to avoid stream-limit exhaustion
- Monitor peer accept-loop health; a crashed handler turns every open_bi into this error
- Treat connect and open_bi failures identically: reconnect and retry once
When it happens
Trigger: Peer disconnected immediately after the handshake; peer sync accept task panicked or exited; concurrent sync requests exhausting the peer's remote bidirectional stream limit; idle timeout firing during open_bi.
Common situations: Peer app being closed while a sync cycle runs; fan-out sync hammering one device with many concurrent requests; peer daemon crash-looping.
Related errors
- Failed to send length: {}
- Failed to send request: {}
- Failed to write length prefix: {}
- Failed to write message: {}
- Failed to finish stream: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/fa3ceeb22134f263.
Report an issue: GitHub.