{"record":{"id":"26ebfe9593d0f1ce","repo":"spacedriveapp/spacedrive","slug":"volume-not-mounted-cannot-verify-path-existence","errorCode":null,"errorMessage":"Volume not mounted, cannot verify path existence","messagePattern":"Volume not mounted, cannot verify path existence","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"core/src/ops/indexing/change_detection/handler.rs","lineNumber":74,"sourceCode":"\n/// Check if a path exists, distinguishing between \"doesn't exist\" and \"can't access\".\n///\n/// Critical for preventing false deletions when volumes go offline.\npub async fn path_exists_safe(\n\tpath: &Path,\n\tbackend: Option<&Arc<dyn crate::volume::VolumeBackend>>,\n) -> Result<bool> {\n\tuse crate::volume::error::VolumeError;\n\n\tif let Some(backend) = backend {\n\t\tmatch backend.exists(path).await {\n\t\t\tOk(exists) => Ok(exists),\n\t\t\tErr(VolumeError::NotMounted(_)) => {\n\t\t\t\ttracing::warn!(\n\t\t\t\t\t\"Volume not mounted when checking path existence: {}\",\n\t\t\t\t\tpath.display()\n\t\t\t\t);\n\t\t\t\tErr(anyhow::anyhow!(\n\t\t\t\t\t\"Volume not mounted, cannot verify path existence\"\n\t\t\t\t))\n\t\t\t}\n\t\t\tErr(VolumeError::Io(ref e)) if e.kind() == std::io::ErrorKind::NotFound => Ok(false),\n\t\t\tErr(VolumeError::Io(io_err)) => {\n\t\t\t\ttracing::warn!(\n\t\t\t\t\t\"IO error when checking path existence for {}: {}\",\n\t\t\t\t\tpath.display(),\n\t\t\t\t\tio_err\n\t\t\t\t);\n\t\t\t\tErr(anyhow::anyhow!(\n\t\t\t\t\t\"IO error, volume may be offline: {}\",\n\t\t\t\t\tio_err\n\t\t\t\t))\n\t\t\t}\n\t\t\tErr(e) => {\n\t\t\t\ttracing::warn!(\n\t\t\t\t\t\"Volume error when checking path existence for {}: {}\",","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/ops/indexing/change_detection/handler.rs#L56-L92","documentation":"During indexing change detection, the volume backend's exists() returned VolumeError::NotMounted. The handler cannot verify whether a changed path still exists, so it warn-logs and returns an error rather than guessing deleted-or-not. The correct mental model is deferred work: once the volume is remounted, a rescan reconciles state.","triggerScenarios":"External drive unplugged, network share disconnected, or cloud volume logged out while the indexer processes events whose paths live on that volume.","commonSituations":"USB drives removed without ejecting, laptops waking before network volumes reconnect, cloud storage credentials expiring mid-session.","solutions":["Remount or reconnect the volume, then trigger a rescan of its location","Pause or skip indexing jobs for volumes known to be offline instead of letting them fail","Check mount status before starting scans over a volume's paths","If the volume is permanently gone, remove its location from the library"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Probe the volume root before running change detection over its paths.\nif let Some(backend) = backend {\n    if matches!(backend.exists(location_root).await, Err(VolumeError::NotMounted(_))) {\n        // volume offline: defer this event batch instead of failing the handler\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Eject volumes cleanly","Reconnect network volumes before resuming indexing","Treat NotMounted as a signal to defer work, not to fail it"],"tags":["indexing","volume","offline","filesystem"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}