{"record":{"id":"2b83c2e403594c58","repo":"spacedriveapp/spacedrive","slug":"transfer-interrupted-received-of-bytes-befo","errorCode":null,"errorMessage":"Transfer interrupted: received {} of {} bytes before connection closed","messagePattern":"Transfer interrupted: received (.+?) of (.+?) bytes before connection closed","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"core/src/ops/files/copy/strategy.rs","lineNumber":740,"sourceCode":"\t\t\t\t}\n\t\t\t\tcrate::service::network::protocol::file_transfer::FileTransferMessage::TransferError {\n\t\t\t\t\tmessage,\n\t\t\t\t\t..\n\t\t\t\t} => {\n\t\t\t\t\t// Clean up partial file\n\t\t\t\t\tlet _ = fs::remove_file(&final_dest_path).await;\n\t\t\t\t\treturn Err(anyhow::anyhow!(\"Transfer error: {}\", message));\n\t\t\t\t}\n\t\t\t\t_ => {\n\t\t\t\t\tdebug!(\"Received unexpected message during PULL transfer\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Verify transfer completed properly\n\t\tif !transfer_completed {\n\t\t\tlet _ = fs::remove_file(&final_dest_path).await;\n\t\t\treturn Err(anyhow::anyhow!(\n\t\t\t\t\"Transfer interrupted: received {} of {} bytes before connection closed\",\n\t\t\t\ttotal_bytes_received,\n\t\t\t\tfile_size\n\t\t\t));\n\t\t}\n\n\t\tfile.flush().await?;\n\t\tfile.sync_all().await?;\n\n\t\tinfo!(\n\t\t\t\"PULL transfer completed: {} bytes from device:{} to {}\",\n\t\t\ttotal_bytes_received,\n\t\t\tsource_device_slug,\n\t\t\tfinal_dest_path.display()\n\t\t);\n\n\t\tctx.log(format!(\n\t\t\t\"PULL transfer completed successfully: {} bytes from device:{} to {}\",","sourceCodeStart":722,"sourceCodeEnd":758,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/files/copy/strategy.rs#L722-L758","documentation":"After the PULL receive loop exits, transfer_completed is still false: the connection closed before the sender's TransferComplete message arrived. The error reports bytes received versus the expected file_size, deletes the partial file, and fails the job. This is the signature of a mid-transfer disconnect rather than a protocol violation.","triggerScenarios":"Network drop (Wi-Fi to VPN switch, sleep), remote daemon restart or crash, relay timeout, or the peer device suspending while streaming chunks - the message loop ends without TransferComplete and the guard at strategy.rs:740 fires.","commonSituations":"Laptop sleep during large transfers, unstable Wi-Fi, router/NAT renewal breaking the QUIC path, remote device rebooting for updates mid-copy.","solutions":["Retry the copy job - the transfer protocol tracks chunk state per session and restarts cleanly","Confirm both devices are online and reachable (same network or relay reachable)","Check the peer daemon for restarts, OOM kills, or panics at the failure timestamp","For flaky links, disable device sleep and prefer wired connections for large files"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-flight: confirm the source device is present in the registry before a large PULL.\nlet networking = ctx.networking_service().context(\"networking required\")?;\nlet registry = networking.device_registry().read().await;\nif registry.get_node_by_device(source_device_id).is_none() {\n    anyhow::bail!(\"source device {} not online; defer the copy\", source_device_id);\n}","typeGuard":null,"tryCatchPattern":"let mut attempt = 0;\nloop {\n    attempt += 1;\n    match run_pull_copy().await {\n        Ok(v) => break Ok(v),\n        Err(ref e) if e.to_string().starts_with(\"Transfer interrupted\") && attempt < 3 => {\n            tokio::time::sleep(std::time::Duration::from_secs(2 * attempt as u64)).await;\n        }\n        Err(e) => break Err(e),\n    }\n}","preventionTips":["Keep both devices awake and on a stable network during transfers","Rely on job resumability - rerun the job instead of salvaging partial files","Watch peer daemon health during long transfers"],"tags":["network","file-transfer","p2p","interruption"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}