spacedriveapp/spacedrive · critical · anyhow::Error

Chunk {} checksum mismatch

Error message

Chunk {} checksum mismatch

What it means

Each FileChunk carries a per-chunk blake3 checksum; recomputing blake3 over the received bytes mismatched (strategy.rs:653-660), so chunk data was corrupted, duplicated, or reordered in flight or in memory. With QUIC's integrity protection, genuine wire corruption is unlikely — suspect a producer bug, memory issue, or build mismatch. Unlike the byte-count and final-checksum failures, this branch returns WITHOUT deleting the partial destination file, so a corrupt partial file remains on disk.

Source

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

			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 msg: crate::service::network::protocol::file_transfer::FileTransferMessage =
				rmp_serde::from_slice(&msg_buf)?;

			match msg {
				crate::service::network::protocol::file_transfer::FileTransferMessage::FileChunk {
					chunk_index,
					data,
					chunk_checksum,
					..
				} => {
					// Verify chunk checksum
					let calculated = blake3::hash(&data);
					if calculated.as_bytes() != &chunk_checksum {
						return Err(anyhow::anyhow!(
							"Chunk {} checksum mismatch",
							chunk_index
						));
					}

					// Write chunk
					file.write_all(&data).await?;
					if let Some(h) = &mut hasher {
						h.update(&data);
					}
					total_bytes_received += data.len() as u64;

					// Progress callback
					if let Some(cb) = progress_callback {
						cb(total_bytes_received, file_size);
					}

					if chunk_index % 100 == 0 {

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Delete any leftover partial file at the destination, then retry the transfer
  2. Verify both devices run identical core versions so chunk framing matches
  3. If it reproduces at the same chunk index, capture sender-side logs and report a protocol bug
  4. If corruption recurs across unrelated transfers, run a memory diagnostic on both machines

Example fix

// before (strategy.rs, current behavior leaves the partial file)
if calculated.as_bytes() != &chunk_checksum {
    return Err(anyhow::anyhow!("Chunk {} checksum mismatch", chunk_index));
}

// after: clean up the corrupt partial file like the other integrity failures
if calculated.as_bytes() != &chunk_checksum {
    let _ = fs::remove_file(&final_dest_path).await;
    return Err(anyhow::anyhow!("Chunk {} checksum mismatch", chunk_index));
}
Defensive patterns

Strategy: retry

Try / catch

match remote_strategy.execute_pull(ctx, &src, &dst).await {
    Ok(n) => Ok(n),
    Err(e) if e.to_string().starts_with("Chunk") && e.to_string().ends_with("checksum mismatch") => {
        // NOTE: strategy does NOT delete the partial file here — remove it before retrying
        let _ = tokio::fs::remove_file(&expected_dest).await;
        remote_strategy.execute_pull(ctx, &src, &dst).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Sender/receiver running mismatched versions that frame chunks differently; buffer corruption under memory pressure; duplicated chunk delivery after a stream event; producer-side serialization bug on the remote.

Common situations: Mixed daemon versions during rolling upgrades; hardware memory errors; reproducible failure at the same chunk index indicating a protocol bug.

Related errors


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