spacedriveapp/spacedrive · error · anyhow::Error

Transfer interrupted: received {} of {} bytes before connect

Error message

Transfer interrupted: received {} of {} bytes before connection closed

What it means

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.

Source

Thrown at core/src/ops/files/copy/strategy.rs:740

				}
				crate::service::network::protocol::file_transfer::FileTransferMessage::TransferError {
					message,
					..
				} => {
					// Clean up partial file
					let _ = fs::remove_file(&final_dest_path).await;
					return Err(anyhow::anyhow!("Transfer error: {}", message));
				}
				_ => {
					debug!("Received unexpected message during PULL transfer");
				}
			}
		}

		// Verify transfer completed properly
		if !transfer_completed {
			let _ = fs::remove_file(&final_dest_path).await;
			return Err(anyhow::anyhow!(
				"Transfer interrupted: received {} of {} bytes before connection closed",
				total_bytes_received,
				file_size
			));
		}

		file.flush().await?;
		file.sync_all().await?;

		info!(
			"PULL transfer completed: {} bytes from device:{} to {}",
			total_bytes_received,
			source_device_slug,
			final_dest_path.display()
		);

		ctx.log(format!(
			"PULL transfer completed successfully: {} bytes from device:{} to {}",

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Retry the copy job - the transfer protocol tracks chunk state per session and restarts cleanly
  2. Confirm both devices are online and reachable (same network or relay reachable)
  3. Check the peer daemon for restarts, OOM kills, or panics at the failure timestamp
  4. For flaky links, disable device sleep and prefer wired connections for large files
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: confirm the source device is present in the registry before a large PULL.
let networking = ctx.networking_service().context("networking required")?;
let registry = networking.device_registry().read().await;
if registry.get_node_by_device(source_device_id).is_none() {
    anyhow::bail!("source device {} not online; defer the copy", source_device_id);
}

Try / catch

let mut attempt = 0;
loop {
    attempt += 1;
    match run_pull_copy().await {
        Ok(v) => break Ok(v),
        Err(ref e) if e.to_string().starts_with("Transfer interrupted") && attempt < 3 => {
            tokio::time::sleep(std::time::Duration::from_secs(2 * attempt as u64)).await;
        }
        Err(e) => break Err(e),
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: Laptop sleep during large transfers, unstable Wi-Fi, router/NAT renewal breaking the QUIC path, remote device rebooting for updates mid-copy.

Understand the failure class

Related errors


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