gitbutlerapp/gitbutler · error
Could not get app data dir
Error message
Could not get app data dir
What it means
`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.
Source
Thrown at crates/but-path/src/lib.rs:55
/// When `E2E_TEST_APP_DATA_DIR` is set, returns `<E2E_TEST_APP_DATA_DIR>/home`
/// so tests never touch the real home directory.
pub fn home_dir() -> Option<PathBuf> {
if let Some(test_dir) = std::env::var_os("E2E_TEST_APP_DATA_DIR") {
return Some(PathBuf::from(test_dir).join("home"));
}
dirs::home_dir()
}
/// Like [`app_data_dir()`], but explicitly for `channel`.
///
/// When `E2E_TEST_APP_DATA_DIR` is set, `channel` is ignored and the result is always
/// `<E2E_TEST_APP_DATA_DIR>/com.gitbutler.app`.
pub fn app_data_dir_for_channel(channel: AppChannel) -> anyhow::Result<PathBuf> {
if let Some(test_dir) = std::env::var_os("E2E_TEST_APP_DATA_DIR") {
return Ok(PathBuf::from(test_dir).join("com.gitbutler.app"));
}
dirs::data_dir()
.ok_or(anyhow::anyhow!("Could not get app data dir"))
.map(|dir| dir.join(identifier_for_channel(channel)))
}
/// The directory to store logs in, **one per channel**.
///
/// > ⚠️Keep in sync with `tauri::AppHandle::path().app_log_dir().`
///
/// # Platform-specific locations
///
/// - **macOS**: `~/Library/Logs/<identifier()>`
/// - **Linux/Windows/other**: `<data_local_dir>/<identifier()>/logs`
///
/// # Testing behavior
///
/// When the `E2E_TEST_APP_DATA_DIR` environment variable is set (used by E2E tests),
/// this function returns `<E2E_TEST_APP_DATA_DIR>/logs` instead of the platform-specific
/// default directories above. This override always ignores the compile-time channel.
pub fn app_log_dir() -> anyhow::Result<PathBuf> {View on GitHub (pinned to caf1f223d3)
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
Example fix
// before
let dir = but_path::app_data_dir()?; // Could not get app data dir
// after
use anyhow::Context;
let dir = but_path::app_data_dir().with_context(|| {
format!(
"resolving app data dir (HOME={:?}, XDG_DATA_HOME={:?})",
std::env::var("HOME"),
std::env::var("XDG_DATA_HOME")
)
})?; Defensive patterns
Strategy: validation
Validate before calling
// Probing what dirs::data_dir() sees, without calling but_path:
fn data_dir_available() -> bool {
std::env::var_os("XDG_DATA_HOME").is_some() || dirs::home_dir().is_some()
}
// or simply provide the override in tests:
// std::env::set_var("E2E_TEST_APP_DATA_DIR", "/tmp/gb-test"); Try / catch
match but_path::app_data_dir_for_channel(channel) {
Ok(dir) => { /* ... */ }
Err(e) => {
log::error!("no data dir; set HOME or XDG_DATA_HOME ({e:#})");
return Err(e);
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Docker containers without USER/HOME setup; systemd services missing `Environment=HOME=...` or running with an empty environment; ssh non-login shells; misconfigured sandboxes.
Related errors
- Could not get app cache dir
- Failed to determine home directory
- missing config dir
- When using OpenAI in a bring your own key configuration, you
- BUG: we do not create or work with symlinks
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/4c9f76f7a6a21d95.
Report an issue: GitHub.