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

  1. Serialize concurrent copy jobs to the same device and retry
  2. Restart both daemons to clear stale transfer sessions
  3. If reproducible with a single in-flight transfer, capture both transfer IDs and report it - it indicates a session-routing bug
  4. 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

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


AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16). Data as JSON: /api/errors/8017b16a60f849de. Report an issue: GitHub.