{"record":{"id":"39d03d7db4214e29","repo":"gitbutlerapp/gitbutler","slug":"cannot-attempt-to-open-anything-but-a-directory","errorCode":null,"errorMessage":"Cannot attempt to open anything but a directory: '{}'","messagePattern":"Cannot attempt to open anything but a directory: '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-tauri/src/debug.rs","lineNumber":40,"sourceCode":"pub fn open_cache_folder() -> Result<(), Error> {\n    open_existing(but_path::app_cache_dir()?)\n}\n\n/// Open `dir` but refuse to do so if that would definitely fail as it's not a directory,\n/// or it doesn't exist.\n///\n/// We can assume the directories exist.\nfn open_existing(dir: impl AsRef<Path>) -> Result<(), Error> {\n    let dir = dir.as_ref();\n    if !dir.exists() {\n        return Err(anyhow!(\n            \"Cannot attempt to open non-existing directory: '{}'\",\n            dir.display()\n        )\n        .into());\n    }\n    if !dir.is_dir() {\n        return Err(anyhow!(\n            \"Cannot attempt to open anything but a directory: '{}'\",\n            dir.display()\n        )\n        .into());\n    }\n\n    let is_macos_stable_build =\n        cfg!(target_os = \"macos\") && matches!(AppChannel::new(), AppChannel::Release);\n    // On macOS stable builds, it would try to open `com.gitbutler.app` and treat it as application,\n    // which would fail. Instead, we reveal, which selects the directory in the finder and users\n    // can right-click it to see the package contents. Better than nothing.\n    // Maybe we can rename the application ID at some point.\n    if is_macos_stable_build {\n        reveal_directory(dir)\n    } else {\n        open::that(dir).map_err(anyhow::Error::from)\n    }\n    .with_context(|| format!(\"Failed to open directory at '{dir}'\", dir = dir.display()))","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-tauri/src/debug.rs#L22-L58","documentation":"Thrown by open_existing() in the gitbutler-tauri debug crate when the path passed to an 'open directory' helper exists on disk but is not a directory (a regular file, symlink to a file, or special file). The helper validates existence first, then requires is_dir() before handing the path to the OS opener/reveal logic. It exists to fail fast instead of letting the platform open() produce a confusing error.","triggerScenarios":"Calling a debug/API command that opens a folder (e.g. logs or app-data directory selection) with a path that resolves to a file; passing a symlink that points at a regular file; a stale path where a directory was replaced by a file of the same name.","commonSituations":"User picks a file instead of a folder in an 'Open Folder' dialog; a configured logs/cache path was recreated as a file by another tool; path typos that land on an existing file like 'logs.txt' instead of 'logs/'. On macOS the path may also be inside the com.gitbutler.app bundle which is specially handled just below this check.","solutions":["Verify the path points to a directory (ls -ld <path> or std::fs::metadata(path).is_dir()) and correct the caller to pass a directory.","If the path is a file that should be a directory, move/delete the file and create the directory.","If a symlink is involved, repoint it at a directory rather than a file.","If you are a caller of open_existing(), pre-validate with the is_dir() check shown below instead of relying on the runtime error."],"exampleFix":"// before\nopen_existing(&config.log_path)?; // panics/errors when log_path is a file\n\n// after\nlet p = config.log_path.as_path();\nif !p.is_dir() {\n    anyhow::bail!(\"log path '{}' is not a directory\", p.display());\n}\nopen_existing(&config.log_path)?;","handlingStrategy":"validation","validationCode":"use std::path::Path;\n\nfn ensure_dir(p: &Path) -> anyhow::Result<()> {\n    let meta = std::fs::symlink_metadata(p)?;\n    if !meta.is_dir() {\n        anyhow::bail!(\"path '{}' is not a directory\", p.display());\n    }\n    Ok(())\n}\n\nensure_dir(&path)?;\nopen_existing(&path)?;","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always resolve user-selected paths through is_dir() before passing to directory-opening helpers.","When configurable, validate configured directories at settings-load time, not at use time.","Resolve symlinks first so file-symlinks are caught early."],"tags":["rust","tauri","filesystem","path-validation","debug-tooling"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}