{"record":{"id":"fadf2be504eb1394","repo":"spacedriveapp/spacedrive","slug":"failed-to-open-stream-fadf2b","errorCode":null,"errorMessage":"Failed to open stream: {}","messagePattern":"Failed to open stream: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"core/src/service/network/transports/sync.rs","lineNumber":127,"sourceCode":"\t\t\t}\n\n\t\t\t// Track outbound connection so we can receive incoming streams on it\n\t\t\tif let Some(cmd_sender) = self.command_sender() {\n\t\t\t\tuse crate::service::network::core::event_loop::EventLoopCommand;\n\t\t\t\tlet _ = cmd_sender.send(EventLoopCommand::TrackOutboundConnection {\n\t\t\t\t\tnode_id,\n\t\t\t\t\tconn: new_conn.clone(),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tnew_conn\n\t\t};\n\n\t\t// Open a unidirectional stream and send the message\n\t\tlet mut send = conn\n\t\t\t.open_uni()\n\t\t\t.await\n\t\t\t.map_err(|e| anyhow::anyhow!(\"Failed to open stream: {}\", e))?;\n\n\t\t// Write length prefix (required by multiplexer)\n\t\tlet len = bytes.len() as u32;\n\t\tsend.write_all(&len.to_be_bytes())\n\t\t\t.await\n\t\t\t.map_err(|e| anyhow::anyhow!(\"Failed to write length prefix: {}\", e))?;\n\n\t\t// Write message bytes\n\t\tsend.write_all(&bytes).await.map_err(|e| {\n\t\t\twarn!(\n\t\t\t\tdevice_uuid = %target_device,\n\t\t\t\terror = %e,\n\t\t\t\t\"Failed to write sync message to stream\"\n\t\t\t);\n\t\t\tanyhow::anyhow!(\"Failed to write message: {}\", e)\n\t\t})?;\n\n\t\tsend.finish()","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/service/network/transports/sync.rs#L109-L145","documentation":"conn.open_uni() failed on the connection used for sending. Because this path reuses cached connections checked with close_reason().is_none(), the typical cause is the connection dying after that liveness check (race), or the peer not accepting unidirectional streams for SYNC_ALPN.","triggerScenarios":"Cached connection died between the liveness check and open_uni; peer idle-timeout; peer restarted with the same NodeId; peer accept loop stopped so uni streams are refused.","commonSituations":"Long-lived daemons holding stale cached connections; laptop sleep/wake invalidating connections underneath the cache.","solutions":["On failure, evict the cache entry and retry once with a fresh connection","Treat open_uni errors on cached connections as a cache-invalidation signal","Verify the peer accepts length-prefixed uni streams (the multiplexer depends on them)"],"exampleFix":"// before\nlet mut send = conn.open_uni().await\n    .map_err(|e| anyhow::anyhow!(\"Failed to open stream: {}\", e))?;\n\n// after\nlet mut send = match conn.open_uni().await {\n    Ok(s) => s,\n    Err(_) => {\n        active_connections.write().await.remove(&cache_key); // evict stale entry\n        let conn = endpoint.connect(node_id, SYNC_ALPN).await?;\n        conn.open_uni().await?\n    }\n};","handlingStrategy":"retry","validationCode":"// Shrink the race before using a cached connection\nlet conn = {\n    let connections = active_connections.read().await;\n    match connections.get(&cache_key) {\n        Some(c) if c.close_reason().is_none() => c.clone(),\n        _ => return reconnect_and_send(device, node_id, bytes).await,\n    }\n};","typeGuard":null,"tryCatchPattern":"match conn.open_uni().await {\n    Ok(send) => send,\n    Err(_) => {\n        // cached connection died after the liveness check: evict and reconnect once\n        active_connections.write().await.remove(&cache_key);\n        let conn = endpoint.connect(node_id, SYNC_ALPN).await?;\n        conn.open_uni().await?\n    }\n}","preventionTips":["Evict cache entries on any open_uni or write failure","Treat cached connections as optimistic; always keep a one-shot reconnect path","Add idle timeouts to the cache so long-dead connections are not reused"],"tags":["network","iroh","quic","cache","sync","rust"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}