{"record":{"id":"4c9f76f7a6a21d95","repo":"gitbutlerapp/gitbutler","slug":"could-not-get-app-data-dir","errorCode":null,"errorMessage":"Could not get app data dir","messagePattern":"Could not get app data dir","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-path/src/lib.rs","lineNumber":55,"sourceCode":"/// When `E2E_TEST_APP_DATA_DIR` is set, returns `<E2E_TEST_APP_DATA_DIR>/home`\n/// so tests never touch the real home directory.\npub fn home_dir() -> Option<PathBuf> {\n    if let Some(test_dir) = std::env::var_os(\"E2E_TEST_APP_DATA_DIR\") {\n        return Some(PathBuf::from(test_dir).join(\"home\"));\n    }\n    dirs::home_dir()\n}\n\n/// Like [`app_data_dir()`], but explicitly for `channel`.\n///\n/// When `E2E_TEST_APP_DATA_DIR` is set, `channel` is ignored and the result is always\n/// `<E2E_TEST_APP_DATA_DIR>/com.gitbutler.app`.\npub fn app_data_dir_for_channel(channel: AppChannel) -> anyhow::Result<PathBuf> {\n    if let Some(test_dir) = std::env::var_os(\"E2E_TEST_APP_DATA_DIR\") {\n        return Ok(PathBuf::from(test_dir).join(\"com.gitbutler.app\"));\n    }\n    dirs::data_dir()\n        .ok_or(anyhow::anyhow!(\"Could not get app data dir\"))\n        .map(|dir| dir.join(identifier_for_channel(channel)))\n}\n\n/// The directory to store logs in, **one per channel**.\n///\n/// > ⚠️Keep in sync with `tauri::AppHandle::path().app_log_dir().`\n///\n/// # Platform-specific locations\n///\n/// - **macOS**: `~/Library/Logs/<identifier()>`\n/// - **Linux/Windows/other**: `<data_local_dir>/<identifier()>/logs`\n///\n/// # Testing behavior\n///\n/// When the `E2E_TEST_APP_DATA_DIR` environment variable is set (used by E2E tests),\n/// this function returns `<E2E_TEST_APP_DATA_DIR>/logs` instead of the platform-specific\n/// default directories above. This override always ignores the compile-time channel.\npub fn app_log_dir() -> anyhow::Result<PathBuf> {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-path/src/lib.rs#L37-L73","documentation":"`app_data_dir_for_channel` returns this when `dirs::data_dir()` is None, i.e. the platform data directory cannot be determined. On Linux that means neither `XDG_DATA_HOME` nor a usable home directory (`HOME`, backed by a passwd lookup) exists; on macOS it means no home directory. The `E2E_TEST_APP_DATA_DIR` override short-circuits before this check.","triggerScenarios":"Running the app or `but` CLI inside a container/systemd service/cron context where HOME is unset and no passwd entry resolves; a stripped-down environment where `HOME` points to a nonexistent path; CI jobs that clear the environment.","commonSituations":"Docker containers without USER/HOME setup; systemd services missing `Environment=HOME=...` or running with an empty environment; ssh non-login shells; misconfigured sandboxes.","solutions":["Set `HOME` to a writable directory (or `XDG_DATA_HOME` on Linux) in the failing environment","For tests or hermetic runs, set `E2E_TEST_APP_DATA_DIR` so the check is bypassed entirely","For services, add `Environment=\"HOME=/var/lib/gitbutler\"` (or equivalent) to the unit file","Wrap the call with `.context(...)` including HOME/XDG_DATA_HOME values to make future diagnosis immediate"],"exampleFix":"// before\nlet dir = but_path::app_data_dir()?; // Could not get app data dir\n\n// after\nuse anyhow::Context;\nlet dir = but_path::app_data_dir().with_context(|| {\n    format!(\n        \"resolving app data dir (HOME={:?}, XDG_DATA_HOME={:?})\",\n        std::env::var(\"HOME\"),\n        std::env::var(\"XDG_DATA_HOME\")\n    )\n})?;","handlingStrategy":"validation","validationCode":"// Probing what dirs::data_dir() sees, without calling but_path:\nfn data_dir_available() -> bool {\n    std::env::var_os(\"XDG_DATA_HOME\").is_some() || dirs::home_dir().is_some()\n}\n// or simply provide the override in tests:\n// std::env::set_var(\"E2E_TEST_APP_DATA_DIR\", \"/tmp/gb-test\");","typeGuard":null,"tryCatchPattern":"match but_path::app_data_dir_for_channel(channel) {\n    Ok(dir) => { /* ... */ }\n    Err(e) => {\n        log::error!(\"no data dir; set HOME or XDG_DATA_HOME ({e:#})\");\n        return Err(e);\n    }\n}","preventionTips":["Always set HOME in containers, systemd units, and cron entries that run GitButler binaries","Set E2E_TEST_APP_DATA_DIR in CI to get deterministic paths and skip platform lookup","Fail startup with a clear message about HOME/XDG env instead of deep inside storage code"],"tags":["rust","filesystem","environment","dirs","xdg"],"backgroundTag":"home-directory-not-found","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}