{"record":{"id":"4c5fe70dd5932c41","repo":"gitbutlerapp/gitbutler","slug":"could-not-get-app-cache-dir","errorCode":null,"errorMessage":"Could not get app cache dir","messagePattern":"Could not get app cache dir","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-path/src/lib.rs","lineNumber":151,"sourceCode":"/// the compile-time or explicit channel.\n///\n/// # Errors\n///\n/// Returns an error if the platform's cache directory cannot be determined.\npub fn app_cache_dir() -> anyhow::Result<PathBuf> {\n    app_cache_dir_for_channel(AppChannel::new())\n}\n\n/// Like [`app_cache_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>/cache`.\npub fn app_cache_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(\"cache\"));\n    }\n    dirs::cache_dir()\n        .ok_or(anyhow::anyhow!(\"Could not get app cache dir\"))\n        .map(|dir| dir.join(identifier_for_channel(channel)))\n}\n\n/// Returns the bundle identifier for the compile-time [`AppChannel`].\npub fn identifier() -> &'static str {\n    identifier_for_channel(AppChannel::new())\n}\n\n/// Returns the bundle identifier used for `channel`.\npub const fn identifier_for_channel(channel: AppChannel) -> &'static str {\n    match channel {\n        AppChannel::Nightly => \"com.gitbutler.app.nightly\",\n        AppChannel::Release => \"com.gitbutler.app\",\n        AppChannel::Dev => \"com.gitbutler.app.dev\",\n    }\n}\n\n/// A way to learn about the currently configured compile-time app-channel.","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-path/src/lib.rs#L133-L169","documentation":"Thrown by `app_cache_dir_for_channel` when `dirs::cache_dir()` returns None, so the platform cache directory cannot be determined and `<cache>/<channel-identifier>` cannot be built. On Linux this requires XDG_CACHE_HOME or HOME; without either, the function raises this error.","triggerScenarios":"Calling `app_cache_dir_for_channel(channel)` (directly or via `app_cache_dir`) when `dirs::cache_dir()` yields None — no XDG_CACHE_HOME and no resolvable HOME; E2E_TEST_APP_DATA_DIR not set.","commonSituations":"Minimal Docker images without HOME; systemd/cron services with empty environments; CI runners executing the app with a sanitized env; chroots lacking /home.","solutions":["Export HOME (or XDG_CACHE_HOME) to a writable path before running","In containers, define ENV HOME=... at image build time","Ensure the target cache directory's parent exists and is writable","In tests, set E2E_TEST_APP_DATA_DIR to bypass platform resolution"],"exampleFix":"// before\n$ docker run image but ...   // no HOME\n\n// after\n$ docker run -e HOME=/home/user image but ...","handlingStrategy":"try-catch","validationCode":"if std::env::var_os(\"HOME\").is_none()\n    && std::env::var_os(\"XDG_CACHE_HOME\").is_none()\n    && std::env::var_os(\"E2E_TEST_APP_DATA_DIR\").is_none()\n{\n    eprintln!(\"Set HOME or XDG_CACHE_HOME before running\");\n}","typeGuard":null,"tryCatchPattern":"match app_cache_dir() {\n    Err(e) if e.to_string().contains(\"app cache dir\") => {\n        eprintln!(\"Cannot resolve cache dir: set HOME/XDG_CACHE_HOME\");\n    }\n    r => r?,\n}","preventionTips":["Define HOME in container images (ENV HOME=/home/user)","Set XDG_CACHE_HOME for services with sanitized environments","Ensure the cache parent directory exists and is writable","Use E2E_TEST_APP_DATA_DIR override in tests"],"tags":["filesystem","directories","cache","environment"],"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"}