spacedriveapp/spacedrive · error · anyhow::Error
Received ack for wrong transfer: expected {}, got {}
Error message
Received ack for wrong transfer: expected {}, got {} What it means
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.
Source
Thrown at core/src/ops/files/copy/strategy.rs:1302
if msg_type[0] != 0 {
return Err(anyhow::anyhow!("Unexpected response type: {}", msg_type[0]));
}
let mut len_buf = [0u8; 4];
recv_stream.read_exact(&mut len_buf).await?;
let msg_len = u32::from_be_bytes(len_buf) as usize;
let mut msg_buf = vec![0u8; msg_len];
recv_stream.read_exact(&mut msg_buf).await?;
let ack_message: crate::service::network::protocol::file_transfer::FileTransferMessage =
rmp_serde::from_slice(&msg_buf)?;
match ack_message {
crate::service::network::protocol::file_transfer::FileTransferMessage::TransferFinalAck { transfer_id: ack_id } => {
if ack_id != transfer_id {
return Err(anyhow::anyhow!("Received ack for wrong transfer: expected {}, got {}", transfer_id, ack_id));
}
ctx.log("Received TransferFinalAck from receiver - transfer confirmed!".to_string());
}
_ => {
return Err(anyhow::anyhow!("Expected TransferFinalAck, got different message type"));
}
}
// Only mark completed after receiver confirms to detect network failures.
file_transfer_protocol.update_session_state(
&transfer_id,
crate::service::network::protocol::file_transfer::TransferState::Completed,
)?;
ctx.log(format!(
"File streaming completed and acknowledged: {} chunks, {} bytes sent to device {}",
chunk_index, bytes_transferred, destination_device_id
));View on GitHub (pinned to 6dfeccf211)
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
Defensive patterns
Strategy: validation
Validate before calling
// Prevent ack cross-talk: keep at most one in-flight transfer per destination device.
// Await each copy job to a device before dispatching the next one to it.
for job in copy_jobs_to_same_device {
run_copy_job(job).await?; // sequential, not spawned in parallel
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Bulk multi-file copies fanned out in parallel, retry storms creating overlapping sessions, daemons resuming persisted sessions after restart.
Related errors
- Transfer error: {}
- Transfer interrupted: received {} of {} bytes before connect
- Failed to open stream: {}
- Failed to write message length: {}
- Failed to write chunk data: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/8017b16a60f849de.
Report an issue: GitHub.