{"record":{"id":"1e287891136e52b5","repo":"espanso/espanso","slug":"unable-to-obtain-dirs-data-local-dir","errorCode":null,"errorMessage":"unable to obtain dirs::data_local_dir()","messagePattern":"unable to obtain dirs::data_local_dir\\(\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"espanso/src/path/mod.rs","lineNumber":248,"sourceCode":"        if runtime_dir.is_dir() {\n            return Some(runtime_dir);\n        }\n    }\n    None\n}\n\nfn get_portable_runtime_path() -> Option<PathBuf> {\n    let espanso_exe_path = std::env::current_exe().expect(\"unable to obtain executable path\");\n    let exe_dir = espanso_exe_path.parent();\n    if let Some(parent) = exe_dir {\n        let config_dir = parent.join(\".espanso-runtime\");\n        return Some(config_dir);\n    }\n    None\n}\n\nfn get_legacy_runtime_dir() -> Option<PathBuf> {\n    let data_dir = dirs::data_local_dir().expect(\"unable to obtain dirs::data_local_dir()\");\n    let espanso_dir = data_dir.join(\"espanso\");\n    if is_legacy_runtime_dir(&espanso_dir) {\n        Some(espanso_dir)\n    } else {\n        None\n    }\n}\n\nfn get_default_runtime_dir() -> Option<PathBuf> {\n    let default_dir = get_default_runtime_path();\n    if default_dir.is_dir() {\n        Some(default_dir)\n    } else {\n        None\n    }\n}\n\nfn get_default_runtime_path() -> PathBuf {","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/espanso/espanso/blob/e6c3736675048026a057f1c4803d59242482fa7b/espanso/src/path/mod.rs#L230-L266","documentation":"get_legacy_runtime_dir panics with 'unable to obtain dirs::data_local_dir()' when the dirs crate cannot resolve the user's local data directory while probing for a legacy (pre-2.1) runtime directory under it. On Linux this requires $XDG_DATA_HOME or $HOME to be set and absolute; on Windows/macOS it effectively always succeeds. The legacy probe exists so espanso can migrate old runtime data, and it hard-fails when the base dir is unknown.","triggerScenarios":"resolve_paths -> get_runtime_dir -> get_legacy_runtime_dir on Linux with HOME unset/relative and XDG_DATA_HOME unset/relative: cron jobs, systemd units without HOME, sudo -i, containers running as a user with no HOME. Triggered on every startup where no portable/default runtime dir exists yet.","commonSituations":"Headless systemd services and CI containers missing HOME, misconfigured XDG_DATA_HOME pointing to a relative path, sudo dropping the environment, freshly provisioned Docker users without a home directory.","solutions":["Export HOME (and optionally XDG_DATA_HOME) as an absolute path in the execution environment before starting espanso.","For systemd units, set User= plus Environment=HOME=/home/user so dirs::data_local_dir() resolves.","Create a runtime dir at the default cache location (dirs::cache_dir()/espanso) or pass --runtime-dir; note the legacy probe still runs, so HOME must be valid regardless.","Run espanso as the logged-in desktop user instead of via sudo/root."],"exampleFix":"// before\n$ env -i /usr/bin/espanso start   # HOME unset\nunable to obtain dirs::data_local_dir()\n// after\n$ HOME=/home/federico XDG_DATA_HOME=/home/federico/.local/share /usr/bin/espanso start","handlingStrategy":"validation","validationCode":"let data_local_ok = match std::env::var(\"XDG_DATA_HOME\") {\n    Ok(v) => std::path::Path::new(&v).is_absolute(),\n    Err(_) => std::env::var(\"HOME\").map(|h| std::path::Path::new(&h).is_absolute()).unwrap_or(false),\n};\nif !data_local_ok { eprintln!(\"set XDG_DATA_HOME or absolute HOME before starting espanso\"); }","typeGuard":"fn legacy_probe_env_ok() -> bool {\n    dirs::data_local_dir().is_some()\n}","tryCatchPattern":"let data_dir = dirs::data_local_dir().unwrap_or_else(|| {\n    eprintln!(\"dirs::data_local_dir() is None: set HOME/XDG_DATA_HOME\");\n    std::process::exit(1);\n});","preventionTips":["Set HOME (and optionally XDG_DATA_HOME) in service managers and CI","Use User=/Environment=HOME= in systemd units rather than running as root","Validate XDG vars are absolute paths; relative values make dirs return None","Pre-create the runtime dir so legacy probing runs in a sane environment"],"tags":["environment","xdg","home","panic","linux"],"backgroundTag":"missing-env-var","analyzedSha":"e6c3736675048026a057f1c4803d59242482fa7b","analyzedAt":"2026-09-06T15:16:34.240Z","contentChangedAt":"2026-09-06T15:16:34.240Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}