{"record":{"id":"75048d4c71deb39d","repo":"spacedriveapp/spacedrive","slug":"failed-to-open-stream","errorCode":null,"errorMessage":"Failed to open stream: {}","messagePattern":"Failed to open stream: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"core/src/ops/files/copy/strategy.rs","lineNumber":1142,"sourceCode":"\t\t.endpoint()\n\t\t.ok_or_else(|| anyhow::anyhow!(\"Networking endpoint not available\"))?;\n\n\tctx.log(format!(\n\t\t\"Opening persistent connection to node {} (device {}) for file transfer\",\n\t\tnode_id, destination_device_id\n\t));\n\n\tlet node_addr = iroh::EndpointAddr::new(node_id);\n\tlet connection = endpoint\n\t\t.connect(node_addr, b\"spacedrive/filetransfer/1\")\n\t\t.await\n\t\t.map_err(|e| anyhow::anyhow!(\"Failed to connect to device: {}\", e))?;\n\n\t// Bidirectional stream allows receiving acknowledgment after transfer completion.\n\tlet (mut send_stream, mut recv_stream) = connection\n\t\t.open_bi()\n\t\t.await\n\t\t.map_err(|e| anyhow::anyhow!(\"Failed to open stream: {}\", e))?;\n\n\tlet chunk_size = 64 * 1024u32;\n\tlet total_chunks = ((total_size + chunk_size as u64 - 1) / chunk_size as u64) as u32;\n\n\tlet transfer_request =\n\t\tcrate::service::network::protocol::file_transfer::FileTransferMessage::TransferRequest {\n\t\t\ttransfer_id,\n\t\t\tfile_metadata,\n\t\t\ttransfer_mode: crate::service::network::protocol::TransferMode::TrustedCopy,\n\t\t\tchunk_size,\n\t\t\ttotal_chunks,\n\t\t\tdestination_path: destination_path.clone(),\n\t\t};\n\n\tlet request_data = rmp_serde::to_vec(&transfer_request)?;\n\n\tctx.log(format!(\n\t\t\"Sending TransferRequest for {} bytes ({} chunks) to destination: {}\",","sourceCodeStart":1124,"sourceCodeEnd":1160,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/files/copy/strategy.rs#L1124-L1160","documentation":"The QUIC connection was established but connection.open_bi() failed, so no bidirectional stream could be opened for the chunk frames. This means the connection died between connect() and stream open, or the peer is not accepting streams for this protocol. The transfer aborts before any file data is sent.","triggerScenarios":"Connection reset immediately after the handshake; peer daemon shutting down and refusing new streams; peer lacks the file-transfer ALPN handler due to version skew; idle timeout expiring between connect and open_bi.","commonSituations":"Peer restarting for updates, version mismatch after one side upgraded, aggressive NAT timeouts on mobile networks.","solutions":["Retry the transfer - it opens a fresh connection","Confirm the peer daemon runs the file transfer handler (same or newer version)","Check peer logs for handler startup failures","If persistent between two specific devices, re-pair them"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// open_bi races connection teardown; one retry on a fresh connection usually clears it.\nlet (mut send_stream, mut recv_stream) = match connection.open_bi().await {\n    Ok(pair) => pair,\n    Err(e) => {\n        tracing::warn!(error = %e, \"open_bi failed, reconnecting\");\n        let connection = endpoint.connect(node_addr, alpn).await?;\n        connection.open_bi().await?\n    }\n};","preventionTips":["Upgrade devices together to keep protocol handlers aligned","Avoid dispatching transfers during daemon maintenance windows"],"tags":["network","iroh","quic","file-transfer"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}