{"record":{"id":"4b08c5236834b427","repo":"gitbutlerapp/gitbutler","slug":"cannot-attempt-to-open-non-existing-directory","errorCode":null,"errorMessage":"Cannot attempt to open non-existing directory: '{}'","messagePattern":"Cannot attempt to open non-existing directory: '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/gitbutler-tauri/src/debug.rs","lineNumber":33,"sourceCode":"#[instrument(err(Debug))]\npub fn open_config_folder() -> Result<(), Error> {\n    open_existing(but_path::app_config_dir()?)\n}\n\n/// Opens the cache folder in the system file manager\n#[instrument(err(Debug))]\npub 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.","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-tauri/src/debug.rs#L15-L51","documentation":"open_existing (crates/gitbutler-tauri/src/debug.rs) powers debug commands like open_cache_folder: it opens a directory with the OS file manager but refuses when dir.exists() is false, erroring with the path included. A sibling check rejects paths that exist but are not directories. It exists so debug helpers fail loudly instead of the OS open failing silently.","triggerScenarios":"Invoking the open-cache-folder debug command before the app ever created its cache directory; but_path::app_cache_dir() resolving to a custom/missing location (XDG_CACHE_HOME override on Linux, portable/shifted app data on Windows/macOS); the cache dir having been deleted while the app runs.","commonSituations":"Debug menu used right after a fresh install before first-run dir creation; users with redirected/overridden cache paths; cache cleaned by disk-cleanup tools mid-session; misbuilt portable installs where the cache path lands somewhere read-only or absent.","solutions":["Trigger normal app usage once so startup code creates the cache directory, then retry","Verify the resolved path: on Linux check $XDG_CACHE_HOME/… overrides, on macOS ~/Library/Caches/…, on Windows the LocalAppData cache dir","Create the directory yourself if the app should be robust here: std::fs::create_dir_all before open_existing","If the path exists but still errors, you are hitting the is_dir branch — make sure it is a directory"],"exampleFix":"// before\nfn open_cache_folder() -> Result<(), Error> {\n    open_existing(but_path::app_cache_dir()?)\n}\n\n// after: ensure the directory exists before opening it\nfn open_cache_folder() -> Result<(), Error> {\n    let dir = but_path::app_cache_dir()?;\n    std::fs::create_dir_all(&dir).ok(); // first run: cache dir may not exist yet\n    open_existing(dir)\n}","handlingStrategy":"validation","validationCode":"let dir = but_path::app_cache_dir()?;\nif !dir.exists() {\n    std::fs::create_dir_all(&dir)?; // first run: create before opening\n}\nopen_existing(dir)?;","typeGuard":"fn existing_directory(p: &Path) -> Option<&Path> {\n    p.exists().then_some(p).filter(|p| p.is_dir())\n}","tryCatchPattern":"match open_existing(but_path::app_cache_dir()?) {\n    Ok(()) => Ok(()),\n    Err(err) if err.to_string().contains(\"non-existing directory\") => {\n        // create and retry once — cache dirs may simply not exist yet on first run\n        let dir = but_path::app_cache_dir()?;\n        std::fs::create_dir_all(&dir)?;\n        open_existing(dir)\n    }\n    Err(err) => Err(err),\n}","preventionTips":["Create app directories at startup (create_dir_all) instead of assuming first-run creation happened","Log the resolved cache path in debug tooling so misdirected XDG_CACHE_HOME/app-data overrides are visible","Treat 'open folder' helpers as best-effort: degrade to showing the path in a message box when the OS open fails"],"tags":["gitbutler","tauri","filesystem","debug","desktop"],"backgroundTag":"directory-not-found","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}