spacedriveapp/spacedrive · error · anyhow::Error

Failed to generate content hash: {}

Error message

Failed to generate content hash: {}

What it means

calculate_file_checksum wraps a failure from ContentHashGenerator::generate_content_hash, invoked when verify_checksum is enabled for a copy to compute the local file's checksum for integrity verification. The underlying cause is almost always filesystem-level: the file could not be opened or read to completion. The anyhow context adds no new information beyond naming the hashing step.

Source

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

	let file_size = metadata.len();
	copy_single_file(
		source,
		destination,
		volume_info,
		ctx,
		verify_checksum,
		file_size,
		progress_callback,
	)
	.await
}

/// Calculate file checksum for integrity verification
async fn calculate_file_checksum(path: &Path) -> Result<String> {
	crate::domain::content_identity::ContentHashGenerator::generate_content_hash(path)
		.await
		.map_err(|e| anyhow::anyhow!("Failed to generate content hash: {}", e))
}

/// Stream file data in chunks to the remote device using a persistent connection
async fn stream_file_data<'a>(
	file_path: &Path,
	transfer_id: uuid::Uuid,
	file_transfer_protocol: &crate::service::network::protocol::FileTransferProtocolHandler,
	total_size: u64,
	destination_device_id: uuid::Uuid,
	destination_path: String,
	file_metadata: crate::service::network::protocol::FileMetadata,
	ctx: &JobContext<'a>,
	progress_callback: Option<&ProgressCallback<'a>>,
) -> Result<()> {
	use blake3::Hasher;
	use tokio::io::{AsyncReadExt, AsyncWriteExt};

	debug!(

View on GitHub (pinned to 6dfeccf211)

Solutions

  1. Verify the file exists and the daemon user can read it at the logged path
  2. Retry once - transient exclusive locks (antivirus scans) usually clear within seconds
  3. Add library roots to antivirus real-time scanning exclusion lists
  4. If integrity verification is optional for this workflow, run the job with verify_checksum disabled

Example fix

// before
let checksum = calculate_file_checksum(&path).await?;

// after - degrade gracefully when verification is optional
let checksum = match calculate_file_checksum(&path).await {
    Ok(c) => Some(c),
    Err(e) if !require_verification => {
        tracing::warn!(error = %e, "checksum verify skipped");
        None
    }
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: retry

Validate before calling

// Verify the file is readable before paying for a hash pass.
let f = tokio::fs::File::open(&path).await
    .with_context(|| format!("cannot open for hashing: {}", path.display()))?;
drop(f);

Try / catch

// Transient read locks (antivirus, other indexers) clear quickly; retry once before failing.
let hash = match calculate_file_checksum(&path).await {
    Ok(h) => h,
    Err(first) => {
        tokio::time::sleep(std::time::Duration::from_secs(2)).await;
        calculate_file_checksum(&path).await.map_err(|_| first)?
    }
};

Prevention

When it happens

Trigger: Calling copy with verify_checksum=true; between transfer completion and hashing the file is deleted, moved, exclusively locked by another process, or the daemon loses read permission; hashing a file truncated by an earlier interrupted write.

Common situations: Antivirus or another indexer holding exclusive locks on Windows; file consumed and deleted by an application immediately after arrival; permissions changed by a sync tool.

Related errors


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