{"record":{"id":"85f59324c8112c8b","repo":"atuinsh/atuin","slug":"could-not-determine-home-directory","errorCode":null,"errorMessage":"could not determine home directory","messagePattern":"could not determine home directory","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-common/src/utils.rs","lineNumber":107,"sourceCode":"    if gitdir.parent().is_some() {\n        // if .git is a file (worktree), resolve to the main repo root\n        if let Some(main_repo) = resolve_git_worktree(&gitdir) {\n            return Some(main_repo);\n        }\n        return Some(gitdir);\n    }\n\n    None\n}\n\n// TODO: more reliable, more tested\n// I don't want to use ProjectDirs, it puts config in awkward places on\n// mac. Data too. Seems to be more intended for GUI apps.\n\npub fn home_dir() -> PathBuf {\n    directories::BaseDirs::new()\n        .map(|d| d.home_dir().to_path_buf())\n        .expect(\"could not determine home directory\")\n}\n\n/// Read an environment variable that must be nonempty.\n///\n/// This function will never return an empty string: if the environment variable is set but empty,\n/// [`None`] is returned.\npub fn env_nonempty(name: &str) -> Option<OsString> {\n    std::env::var_os(name).filter(|value| !value.is_empty())\n}\n\npub fn config_dir() -> PathBuf {\n    let config_dir: PathBuf =\n        env_nonempty(\"XDG_CONFIG_HOME\").map_or_else(|| home_dir().join(\".config\"), Into::into);\n    config_dir.join(\"atuin\")\n}\n\npub fn data_dir() -> PathBuf {\n    let data_dir: PathBuf = env_nonempty(\"XDG_DATA_HOME\")","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/atuinsh/atuin/blob/202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1/crates/atuin-common/src/utils.rs#L89-L125","documentation":"home_dir() resolves the user home via directories::BaseDirs::new(), which on Unix reads $HOME. BaseDirs::new() returns None when no home can be determined (HOME unset or empty; on Windows a failed known-folder lookup). Because atuin's config dir, data dir, and database paths all hang off home_dir(), the expect crashes essentially any atuin command.","triggerScenarios":"Any atuin invocation in a process whose environment lacks HOME: systemd services without Environment=, cron jobs, docker run without HOME set, env -i, or a service user with no usable passwd entry.","commonSituations":"Running the atuin daemon or server as a systemd unit without HOME; Docker images that set USER but not HOME; cron and CI runners; sudo with env_reset.","solutions":["Set HOME explicitly for the service or container: systemd Environment=\"HOME=/var/lib/atuin\", docker run -e HOME=/home/atuin","Run atuin under a real user account whose passwd entry defines a home (check with getent passwd <user>)","For systemd units prefer User= plus StateDirectory=/HomeDirectory= so the manager provisions the home"],"exampleFix":"# before (systemd unit)\n[Service]\nExecStart=/usr/bin/atuin daemon\n\n# after\n[Service]\nUser=atuin\nEnvironment=HOME=/var/lib/atuin\nStateDirectory=atuin\nExecStart=/usr/bin/atuin daemon","handlingStrategy":"validation","validationCode":"if cfg!(unix) && std::env::var_os(\"HOME\").map_or(true, |h| h.is_empty()) {\n    eprintln!(\"HOME is not set; atuin needs it to locate its config and database\");\n    std::process::exit(2);\n}","typeGuard":null,"tryCatchPattern":"let home = std::panic::catch_unwind(atuin_common::utils::home_dir)\n    .expect(\"HOME must be set; fix the service environment instead of bypassing\");","preventionTips":["Always define HOME for services and containers that run atuin","Check `getent passwd <user>` shows a home before running atuin as that user","Add a fail-fast startup guard for missing HOME with a clear message"],"tags":["rust","directories","home-directory","environment","panic","systemd"],"backgroundTag":"missing-home-env-var","analyzedSha":"202f6ad98ee0da165c35cdb2afbc5b13d6ab81a1","analyzedAt":"2026-08-16T19:30:24.731Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}