{"record":{"id":"8017b16a60f849de","repo":"spacedriveapp/spacedrive","slug":"received-ack-for-wrong-transfer-expected-got","errorCode":null,"errorMessage":"Received ack for wrong transfer: expected {}, got {}","messagePattern":"Received ack for wrong transfer: expected (.+?), got (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"core/src/ops/files/copy/strategy.rs","lineNumber":1302,"sourceCode":"\n\tif msg_type[0] != 0 {\n\t\treturn Err(anyhow::anyhow!(\"Unexpected response type: {}\", msg_type[0]));\n\t}\n\n\tlet mut len_buf = [0u8; 4];\n\trecv_stream.read_exact(&mut len_buf).await?;\n\tlet msg_len = u32::from_be_bytes(len_buf) as usize;\n\n\tlet mut msg_buf = vec![0u8; msg_len];\n\trecv_stream.read_exact(&mut msg_buf).await?;\n\n\tlet ack_message: crate::service::network::protocol::file_transfer::FileTransferMessage =\n\t\trmp_serde::from_slice(&msg_buf)?;\n\n\tmatch ack_message {\n\t\tcrate::service::network::protocol::file_transfer::FileTransferMessage::TransferFinalAck { transfer_id: ack_id } => {\n\t\t\tif ack_id != transfer_id {\n\t\t\t\treturn Err(anyhow::anyhow!(\"Received ack for wrong transfer: expected {}, got {}\", transfer_id, ack_id));\n\t\t\t}\n\t\t\tctx.log(\"Received TransferFinalAck from receiver - transfer confirmed!\".to_string());\n\t\t}\n\t\t_ => {\n\t\t\treturn Err(anyhow::anyhow!(\"Expected TransferFinalAck, got different message type\"));\n\t\t}\n\t}\n\n\t// Only mark completed after receiver confirms to detect network failures.\n\tfile_transfer_protocol.update_session_state(\n\t\t&transfer_id,\n\t\tcrate::service::network::protocol::file_transfer::TransferState::Completed,\n\t)?;\n\n\tctx.log(format!(\n\t\t\"File streaming completed and acknowledged: {} chunks, {} bytes sent to device {}\",\n\t\tchunk_index, bytes_transferred, destination_device_id\n\t));","sourceCodeStart":1284,"sourceCodeEnd":1320,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/files/copy/strategy.rs#L1284-L1320","documentation":"The final ack arrived and decoded, but its transfer_id belongs to a different transfer than the one just streamed. The stream delivered an ack for a concurrent or stale session - a correlation problem, not a network failure. UUID collisions are effectively impossible, so concurrent transfers sharing connection state or stale peer sessions are the realistic causes.","triggerScenarios":"Two copy jobs to the same device running concurrently over shared connection state; a stale session on the peer answered the read first; peer session bookkeeping mixed up after a reconnect.","commonSituations":"Bulk multi-file copies fanned out in parallel, retry storms creating overlapping sessions, daemons resuming persisted sessions after restart.","solutions":["Serialize concurrent copy jobs to the same device and retry","Restart both daemons to clear stale transfer sessions","If reproducible with a single in-flight transfer, capture both transfer IDs and report it - it indicates a session-routing bug","Upgrade both devices if either runs older session-management code"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Prevent ack cross-talk: keep at most one in-flight transfer per destination device.\n// Await each copy job to a device before dispatching the next one to it.\nfor job in copy_jobs_to_same_device {\n    run_copy_job(job).await?; // sequential, not spawned in parallel\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Await completion of one transfer to a device before starting the next","Restart daemons after crashes to clear stale transfer sessions","Report reproducible wrong-ack cases with both transfer IDs"],"tags":["network","file-transfer","sessions","concurrency"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}