spacedriveapp/spacedrive · error · std::io::Error
Checksum verification failed: source={}, dest={}
Error message
Checksum verification failed: source={}, dest={} What it means
After a copy with verify_checksum enabled, the code finalizes two blake3 hashers (one fed from the source stream, one from the destination stream) and compares digests. A mismatch means the bytes written differ from the bytes read; the destination file is deleted and ErrorKind::InvalidData is returned with both hex digests for post-mortem correlation.
Source
Thrown at core/src/ops/files/copy/strategy.rs:962
dest_file.flush().await?;
dest_file.sync_all().await?;
if let Some(callback) = progress_callback {
callback(file_size, u64::MAX);
ctx.log(format!(
"Strategy final progress: {} / {} bytes (100%)",
total_copied, file_size
));
}
if verify_checksum {
if let (Some(source_hasher), Some(dest_hasher)) = (source_hasher, dest_hasher) {
let source_hash = source_hasher.finalize();
let dest_hash = dest_hasher.finalize();
if source_hash != dest_hash {
let _ = fs::remove_file(destination).await;
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!(
"Checksum verification failed: source={}, dest={}",
source_hash.to_hex(),
dest_hash.to_hex()
),
));
}
ctx.log(format!(
"Checksum verification passed for {}: {}",
destination.display(),
source_hash.to_hex()
));
}
}
let source_metadata = fs::metadata(source).await?;View on GitHub (pinned to 6dfeccf211)
Solutions
- Retry the copy once: transient media and network glitches are the most common cause and the code already removed the bad destination
- If it fails repeatedly on the same file, hash the source twice and compare: a changing digest means the source is being modified during the read, not the copy is broken
- Check destination disk health (smartctl) and cabling, or copy to a different volume to isolate the failing side
- Pause other writers (sync/index jobs, editors) that may touch the source during the copy
Example fix
// before: single attempt, mismatch fails the whole job
copy(...).await?;
// after: retry once on checksum mismatch, then escalate
for attempt in 0..2 {
match copy(...).await {
Err(e) if e.kind() == std::io::ErrorKind::InvalidData && attempt == 0 => continue,
other => break other?,
}
} Defensive patterns
Strategy: retry
Validate before calling
// Before a critical copy, confirm the source is quiescent (two reads, same digest) let h1 = blake3::hash(&tokio::fs::read(src).await?); tokio::time::sleep(Duration::from_millis(250)).await; let h2 = blake3::hash(&tokio::fs::read(src).await?); assert_eq!(h1, h2, "source is being modified concurrently; copying now will fail verification");
Try / catch
match copy_result {
Err(e) if e.kind() == std::io::ErrorKind::InvalidData && e.to_string().contains("Checksum") => {
retry_with_backoff(/* once */).await // transient media glitch most of the time
}
other => other?,
} Prevention
- Enable verify_checksum for any copy onto removable or network media
- Quiesce the source (stop cameras/sync writers) before verified copies
- Capture both digests from the message in logs: they identify which side changed
When it happens
Trigger: Source file modified concurrently while being read (hash computed over a moving target); failing disk or flaky USB cable corrupting writes mid-transfer; destination on a buggy FUSE/network filesystem that alters data; oversized writes silently truncated; antivirus/backup agents touching the file between write and flush.
Common situations: Copying photos off a camera SD card while the camera is still mounted for writing; copying to a failing HDD or a saturated network share; exotic filesystems (exFAT on some kernels, network volumes) with write quirks.
Related errors
- Checksum verification failed
- Final checksum mismatch
- Failed to generate content hash: {}
- Failed to calculate checksum: {}
- Chunk {} checksum mismatch
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/fda94cee88810de8.
Report an issue: GitHub.