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
- Verify the file exists and the daemon user can read it at the logged path
- Retry once - transient exclusive locks (antivirus scans) usually clear within seconds
- Add library roots to antivirus real-time scanning exclusion lists
- 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
- Exclude library directories from antivirus real-time scanning
- Ensure the daemon account has read access to destination paths
- Avoid scheduling competing jobs over the same files
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
- Checksum verification failed
- Checksum verification failed: source={}, dest={}
- Final checksum mismatch
- Path does not exist: {}
- Path must be a directory: {}
AI-assisted analysis of spacedriveapp/spacedrive@6dfeccf211 (2026-08-16).
Data as JSON: /api/errors/e318f6e0a6346e92.
Report an issue: GitHub.