{"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/58e5313667b857ef39a730e380af31816a7b1768/crates/but-path/src/lib.rs#L37-L73","documentation":"Thrown by `app_data_dir_for_channel` when `dirs::data_dir()` returns None, meaning the platform's user data directory cannot be determined. On Linux this happens when XDG_DATA_HOME is unset and $HOME is also unset/unresolvable, so there is no base directory under which to build `<data>/com.gitbutler.app`.","triggerScenarios":"Calling `app_data_dir_for_channel(channel)` (directly or via `app_data_dir`) on a system where `dirs::data_dir()` yields None — typically Linux with no HOME and no XDG_DATA_HOME; E2E_TEST_APP_DATA_DIR override not set.","commonSituations":"Running the app or CLI in a bare Docker container without HOME set; systemd services with a sanitized environment; cron jobs lacking HOME; headless CI runners with minimal env.","solutions":["Ensure HOME is set and points to a writable directory (export HOME=/home/user)","Set XDG_DATA_HOME explicitly (e.g. export XDG_DATA_HOME=$HOME/.local/share)","In containers, create the user/home before running the app (useradd or -e HOME=/tmp)","For tests, set E2E_TEST_APP_DATA_DIR to a writable path to bypass the platform lookup"],"exampleFix":"// before (Docker)\nCMD [\"but\", ...]  // HOME unset\n\n// after\nENV HOME=/home/but\nCMD [\"but\", ...]","handlingStrategy":"try-catch","validationCode":"// caller pre-check\nif std::env::var_os(\"HOME\").is_none()\n    && std::env::var_os(\"XDG_DATA_HOME\").is_none()\n    && std::env::var_os(\"E2E_TEST_APP_DATA_DIR\").is_none()\n{\n    eprintln!(\"Set HOME or XDG_DATA_HOME before starting\");\n}","typeGuard":null,"tryCatchPattern":"match app_data_dir() {\n    Err(e) if e.to_string().contains(\"app data dir\") => {\n        eprintln!(\"No user data dir available: set HOME/XDG_DATA_HOME\");\n    }\n    r => r?,\n}","preventionTips":["Always run with a defined, writable HOME in containers and services","Set XDG base dirs explicitly in Dockerfiles and unit files (Environment=HOME=...)","Set E2E_TEST_APP_DATA_DIR in integration tests for deterministic paths","Create user accounts (not bare root) for services that run the app"],"tags":["filesystem","directories","environment","cross-platform"],"backgroundTag":"missing-config-file","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}