spacedriveapp/spacedrive · error · anyhow::Error

Failed to calculate checksum

Error message

Failed to calculate checksum: {}

What it means

Before initiating a PUSH, the strategy hashes the entire local file with calculate_file_checksum (blake3). Any I/O error while opening or reading the file content is wrapped into this message. The tokio::fs::metadata call just above (strategy.rs:323) succeeded, so this specifically means reading the file's bytes failed after the file was statted.

Solutions

  1. Confirm the source path still exists and the daemon user has read permission, then retry
  2. Re-run the job — transient file locks often clear immediately
  3. Exclude the daemon's data/spaces from antivirus scanning or grant the daemon read access
  4. If the volume was unmounted, remount it and re-dispatch the job

Example fix

// before
let checksum = calculate_file_checksum(local_path)
    .await
    .map(Some)
    .map_err(|e| anyhow::anyhow!("Failed to calculate checksum: {}", e))?;

// after: classify instead of blanket-failing
let checksum = match calculate_file_checksum(local_path).await {
    Ok(c) => Some(c),
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
        return Err(anyhow::anyhow!("source file vanished: {}", local_path.display()));
    }
    Err(e) => {
        tracing::warn!(error = %e, "checksum computation failed; continuing without");
        None
    }
};
Defensive patterns

Strategy: retry

Validate before calling

let meta = tokio::fs::metadata(&path).await?;
if meta.is_dir() { return Err(anyhow::anyhow!("source is a directory")); }
let f = tokio::fs::File::open(&path).await?; // proves readability before the job starts
drop(f);

Try / catch

match calculate_file_checksum(&path).await {
    Ok(c) => c,
    Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Err(anyhow::anyhow!("source vanished: {}", path.display())),
    Err(e) => { tracing::warn!(%e, "transient read failure; retrying once"); calculate_file_checksum(&path).await? }
}

Prevention

When it happens

Trigger: Source file deleted, renamed, or locked between the metadata call and the checksum read; permission denied for read access; failing disk or reader error mid-file; volume unmounted after stat.

Common situations: Antivirus or indexer locks the file on Windows; concurrent job moves the file during the copy; file on an ejected external drive; restrictive permissions after a backup restore.

Related errors


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

Appendix: source

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

			"RemoteTransferStrategy PUSH: {} -> device:{} ({})",
			source, dest_device_slug, dest_device_id
		);

		let networking = ctx
			.networking_service()
			.ok_or_else(|| anyhow::anyhow!("Networking service not available"))?;

		let local_path = source
			.as_local_path()
			.ok_or_else(|| anyhow::anyhow!("Source must be local path for PUSH operation"))?;

		let metadata = tokio::fs::metadata(local_path).await?;
		let file_size = metadata.len();

		let checksum = calculate_file_checksum(local_path)
			.await
			.map(Some)
			.map_err(|e| anyhow::anyhow!("Failed to calculate checksum: {}", e))?;

		info!(
			"Initiating PUSH transfer: {} ({} bytes) -> device:{} ({})",
			local_path.display(),
			file_size,
			dest_device_slug,
			dest_device_id
		);

		ctx.log(format!(
			"Initiating PUSH transfer: {} ({} bytes) -> device:{} ({})",
			local_path.display(),
			file_size,
			dest_device_slug,
			dest_device_id
		));

		let file_metadata = crate::service::network::protocol::FileMetadata {

View on GitHub (pinned to 6dfeccf211)