{"record":{"id":"1e3531bad0442dfe","repo":"spacedriveapp/spacedrive","slug":"path-must-be-a-directory","errorCode":null,"errorMessage":"Path must be a directory: {}","messagePattern":"Path must be a directory: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"apps/cli/src/domains/location/mod.rs","lineNumber":158,"sourceCode":"\tprintln!(\"\\n=== Add New Location ===\\n\");\n\n\t// 1. Location type\n\tlet location_type = select(\n\t\t\"What type of location would you like to add?\",\n\t\t&[\"Local filesystem\".to_string(), \"Cloud storage\".to_string()],\n\t)?;\n\n\tlet sd_path = if location_type == 0 {\n\t\t// Local filesystem\n\t\tlet path_str = text(\"Enter the local path\", false)?.unwrap();\n\t\tlet path_buf = std::path::PathBuf::from(path_str);\n\n\t\t// Validate that path exists\n\t\tif !path_buf.exists() {\n\t\t\tanyhow::bail!(\"Path does not exist: {}\", path_buf.display());\n\t\t}\n\t\tif !path_buf.is_dir() {\n\t\t\tanyhow::bail!(\"Path must be a directory: {}\", path_buf.display());\n\t\t}\n\n\t\tSdPath::local(path_buf)\n\t} else {\n\t\t// Cloud storage\n\t\tuse sd_core::ops::volumes::list::VolumeListQueryInput;\n\n\t\tlet volumes: sd_core::ops::volumes::list::VolumeListOutput = execute_query!(\n\t\t\tctx,\n\t\t\tVolumeListQueryInput {\n\t\t\t\tfilter: sd_core::ops::volumes::VolumeFilter::TrackedOnly\n\t\t\t}\n\t\t);\n\n\t\tif volumes.volumes.is_empty() {\n\t\t\tanyhow::bail!(\n\t\t\t\t\"No cloud volumes found. Add a cloud volume first with:\\n  sd volume add-cloud\"\n\t\t\t);","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/apps/cli/src/domains/location/mod.rs#L140-L176","documentation":"Thrown by the interactive location-add flow when the entered path exists (PathBuf::exists() is true) but PathBuf::is_dir() is false, i.e. the user pointed the location at a regular file. Locations index directory trees, so a file path is rejected.","triggerScenarios":"Entering a file path such as /home/user/movie.mp4 (or a symlink that resolves to a file) in the local path prompt.","commonSituations":"User wants to track a single file and doesn't realize locations are directory-scoped; autocomplete in the terminal completes to a filename; special files like /dev/null or FIFOs also fail is_dir().","solutions":["Point the location at the directory containing the file, e.g. /home/user instead of /home/user/movie.mp4","Check for a trailing filename or accidental paste in the prompt","If the path is a symlink, make sure it resolves to a directory"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let meta = std::fs::metadata(&path_buf)?;\nif !meta.is_dir() {\n    eprintln!(\"'{}' is a file; locations must be directories\", path_buf.display());\n    return Ok(());\n}","typeGuard":"fn is_directory(p: &std::path::Path) -> bool {\n    p.is_dir()\n}","tryCatchPattern":null,"preventionTips":["Locations are directory-scoped by design - never point one at a single file","Check tab-completed paths for an accidental trailing filename","Resolve symlinks first (fs::canonicalize) to see what the path really is"],"tags":["cli","location","filesystem","validation"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}