spacedriveapp/spacedrive · error · anyhow::Error
Failed to open bidirectional stream: {}
Error message
Failed to open bidirectional stream: {} What it means
After connecting, execute_pull opens a bidirectional iroh stream (open_bi) to exchange the PullRequest and file data (strategy.rs:500-503). Failure means the connection dropped or the peer refused the stream: the remote closed the connection, its file-transfer handler is not accepting streams on this ALPN (version mismatch), or the peer shut down between connect and open.
Source
Thrown at core/src/ops/files/copy/strategy.rs:503
.endpoint()
.ok_or_else(|| anyhow::anyhow!("Networking endpoint not available"))?;
ctx.log(format!(
"Opening PULL connection to node {} (device {})",
node_id, source_device_id
));
// Connect to remote device
let node_addr = iroh::EndpointAddr::new(node_id);
let connection = endpoint
.connect(node_addr, b"spacedrive/filetransfer/1")
.await
.map_err(|e| anyhow::anyhow!("Failed to connect to device: {}", e))?;
let (mut send_stream, mut recv_stream) = connection
.open_bi()
.await
.map_err(|e| anyhow::anyhow!("Failed to open bidirectional stream: {}", e))?;
// Send PullRequest
let transfer_id = uuid::Uuid::new_v4();
let current_device_id = crate::device::get_current_device_id();
// Normalize path separators to forward slashes for cross-platform transmission.
// The receiving device may use a different OS separator (Windows \ vs Unix /).
let normalized_source_path =
PathBuf::from(source_path.to_string_lossy().replace('\\', "/"));
let pull_request =
crate::service::network::protocol::file_transfer::FileTransferMessage::PullRequest {
transfer_id,
source_path: normalized_source_path,
requested_by: current_device_id,
};
let request_data = rmp_serde::to_vec(&pull_request)?;
ctx.log(format!(View on GitHub (pinned to 6dfeccf211)
Solutions
- Retry the pull after a short delay — transient stream resets usually clear
- Verify the remote daemon runs a version with the filetransfer ALPN stream handler
- Reduce concurrent cross-device jobs against the same peer
- Check the remote daemon's logs for stream accept errors at the failure time
Defensive patterns
Strategy: retry
Try / catch
match connection.open_bi().await {
Ok(pair) => pair,
Err(e) => {
tracing::warn!(%e, "open_bi failed; reconnecting once");
let connection = endpoint.connect(node_addr, b"spacedrive/filetransfer/1").await?;
connection.open_bi().await?
}
} Prevention
- Reconnect and reopen the stream once before failing the job
- Limit concurrent cross-device jobs per peer to avoid stream exhaustion
- Verify both sides run the filetransfer ALPN handler before large transfers
When it happens
Trigger: Peer closes the connection immediately after accepting it; remote daemon version lacks the filetransfer stream handler; connection reset mid-handshake; peer at its concurrent stream limit.
Common situations: Rolling upgrades where one side can connect but not serve the protocol; peer overloaded by parallel transfers; flaky links resetting streams.
Related errors
- Failed to connect to device: {}
- Source must be a physical path for PULL operation
- Destination must be local path for PULL operation
- Could not resolve source device slug '{}' to UUID in library
- Could not find node_id for device {} (slug: {}). Device may
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/5447ee13ef03409d.
Report an issue: GitHub.