{"record":{"id":"5447ee13ef03409d","repo":"spacedriveapp/spacedrive","slug":"failed-to-open-bidirectional-stream","errorCode":null,"errorMessage":"Failed to open bidirectional stream: {}","messagePattern":"Failed to open bidirectional stream: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"core/src/ops/files/copy/strategy.rs","lineNumber":503,"sourceCode":"\t\t\t.endpoint()\n\t\t\t.ok_or_else(|| anyhow::anyhow!(\"Networking endpoint not available\"))?;\n\n\t\tctx.log(format!(\n\t\t\t\"Opening PULL connection to node {} (device {})\",\n\t\t\tnode_id, source_device_id\n\t\t));\n\n\t\t// Connect to remote device\n\t\tlet node_addr = iroh::EndpointAddr::new(node_id);\n\t\tlet connection = endpoint\n\t\t\t.connect(node_addr, b\"spacedrive/filetransfer/1\")\n\t\t\t.await\n\t\t\t.map_err(|e| anyhow::anyhow!(\"Failed to connect to device: {}\", e))?;\n\n\t\tlet (mut send_stream, mut recv_stream) = connection\n\t\t\t.open_bi()\n\t\t\t.await\n\t\t\t.map_err(|e| anyhow::anyhow!(\"Failed to open bidirectional stream: {}\", e))?;\n\n\t\t// Send PullRequest\n\t\tlet transfer_id = uuid::Uuid::new_v4();\n\t\tlet current_device_id = crate::device::get_current_device_id();\n\t\t// Normalize path separators to forward slashes for cross-platform transmission.\n\t\t// The receiving device may use a different OS separator (Windows \\ vs Unix /).\n\t\tlet normalized_source_path =\n\t\t\tPathBuf::from(source_path.to_string_lossy().replace('\\\\', \"/\"));\n\t\tlet pull_request =\n\t\t\tcrate::service::network::protocol::file_transfer::FileTransferMessage::PullRequest {\n\t\t\t\ttransfer_id,\n\t\t\t\tsource_path: normalized_source_path,\n\t\t\t\trequested_by: current_device_id,\n\t\t\t};\n\n\t\tlet request_data = rmp_serde::to_vec(&pull_request)?;\n\n\t\tctx.log(format!(","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/files/copy/strategy.rs#L485-L521","documentation":"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.","triggerScenarios":"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.","commonSituations":"Rolling upgrades where one side can connect but not serve the protocol; peer overloaded by parallel transfers; flaky links resetting streams.","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"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match connection.open_bi().await {\n    Ok(pair) => pair,\n    Err(e) => {\n        tracing::warn!(%e, \"open_bi failed; reconnecting once\");\n        let connection = endpoint.connect(node_addr, b\"spacedrive/filetransfer/1\").await?;\n        connection.open_bi().await?\n    }\n}","preventionTips":["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"],"tags":["rust","spacedrive","pull","iroh","stream","network","cross-device"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}