{"record":{"id":"7d2f886ecc35047d","repo":"spacedriveapp/spacedrive","slug":"failed-to-calculate-checksum","errorCode":null,"errorMessage":"Failed to calculate checksum: {}","messagePattern":"Failed to calculate checksum: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"core/src/ops/files/copy/strategy.rs","lineNumber":329,"sourceCode":"\t\t\t\"RemoteTransferStrategy PUSH: {} -> device:{} ({})\",\n\t\t\tsource, dest_device_slug, dest_device_id\n\t\t);\n\n\t\tlet networking = ctx\n\t\t\t.networking_service()\n\t\t\t.ok_or_else(|| anyhow::anyhow!(\"Networking service not available\"))?;\n\n\t\tlet local_path = source\n\t\t\t.as_local_path()\n\t\t\t.ok_or_else(|| anyhow::anyhow!(\"Source must be local path for PUSH operation\"))?;\n\n\t\tlet metadata = tokio::fs::metadata(local_path).await?;\n\t\tlet file_size = metadata.len();\n\n\t\tlet checksum = calculate_file_checksum(local_path)\n\t\t\t.await\n\t\t\t.map(Some)\n\t\t\t.map_err(|e| anyhow::anyhow!(\"Failed to calculate checksum: {}\", e))?;\n\n\t\tinfo!(\n\t\t\t\"Initiating PUSH transfer: {} ({} bytes) -> device:{} ({})\",\n\t\t\tlocal_path.display(),\n\t\t\tfile_size,\n\t\t\tdest_device_slug,\n\t\t\tdest_device_id\n\t\t);\n\n\t\tctx.log(format!(\n\t\t\t\"Initiating PUSH transfer: {} ({} bytes) -> device:{} ({})\",\n\t\t\tlocal_path.display(),\n\t\t\tfile_size,\n\t\t\tdest_device_slug,\n\t\t\tdest_device_id\n\t\t));\n\n\t\tlet file_metadata = crate::service::network::protocol::FileMetadata {","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/files/copy/strategy.rs#L311-L347","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Confirm the source path still exists and the daemon user has read permission, then retry","Re-run the job — transient file locks often clear immediately","Exclude the daemon's data/spaces from antivirus scanning or grant the daemon read access","If the volume was unmounted, remount it and re-dispatch the job"],"exampleFix":"// before\nlet checksum = calculate_file_checksum(local_path)\n    .await\n    .map(Some)\n    .map_err(|e| anyhow::anyhow!(\"Failed to calculate checksum: {}\", e))?;\n\n// after: classify instead of blanket-failing\nlet checksum = match calculate_file_checksum(local_path).await {\n    Ok(c) => Some(c),\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound => {\n        return Err(anyhow::anyhow!(\"source file vanished: {}\", local_path.display()));\n    }\n    Err(e) => {\n        tracing::warn!(error = %e, \"checksum computation failed; continuing without\");\n        None\n    }\n};","handlingStrategy":"retry","validationCode":"let meta = tokio::fs::metadata(&path).await?;\nif meta.is_dir() { return Err(anyhow::anyhow!(\"source is a directory\")); }\nlet f = tokio::fs::File::open(&path).await?; // proves readability before the job starts\ndrop(f);","typeGuard":null,"tryCatchPattern":"match calculate_file_checksum(&path).await {\n    Ok(c) => c,\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound => return Err(anyhow::anyhow!(\"source vanished: {}\", path.display())),\n    Err(e) => { tracing::warn!(%e, \"transient read failure; retrying once\"); calculate_file_checksum(&path).await? }\n}","preventionTips":["Verify the source file is readable at job dispatch and again at execution start","Exclude daemon data directories from antivirus scanning on Windows","Avoid moving/deleting files that have copy jobs queued against them"],"tags":["rust","spacedrive","push","checksum","io","blake3"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}