{"record":{"id":"b143577c96a0ed23","repo":"Morganamilo/paru","slug":"failed-to-find-state-directory","errorCode":null,"errorMessage":"failed to find state directory","messagePattern":"failed to find state directory","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/config.rs","lineNumber":588,"sourceCode":"            CallbackKind::Directive(_, key, value) => self.parse_directive(key, value),\n        };\n\n        let filename = cb.filename.unwrap_or(\"paru.conf\");\n        err.map_err(|e| anyhow!(\"{}:{}: {}\", filename, cb.line_number, e))\n    }\n}\n\nimpl Config {\n    pub fn new() -> Result<Self> {\n        let cache =\n            dirs::cache_dir().ok_or_else(|| anyhow!(tr!(\"failed to find cache directory\")))?;\n        let cache = cache.join(\"paru\");\n        let config =\n            dirs::config_dir().ok_or_else(|| anyhow!(tr!(\"failed to find config directory\")))?;\n        let config = config.join(\"paru\");\n        let state = dirs::state_dir()\n            .or_else(dirs::cache_dir)\n            .ok_or_else(|| anyhow!(tr!(\"failed to find state directory\")))?;\n        let state = state.join(\"paru\");\n\n        let build_dir = cache.join(\"clone\");\n        let old_old_devel_path = cache.join(\"devel.json\");\n        let old_devel_path = state.join(\"devel.json\");\n        let devel_path = state.join(\"devel.toml\");\n        let config_path = config.join(\"paru.conf\");\n\n        let old = if old_devel_path.exists() {\n            Some(&old_devel_path)\n        } else if old_old_devel_path.exists() {\n            Some(&old_old_devel_path)\n        } else {\n            None\n        };\n\n        let cache_dir = cache;\n        let state_dir = state;","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/Morganamilo/paru/blob/9ac3578807a87858651e81a02586ceb947686e7c/src/config.rs#L570-L606","documentation":"Config::new() resolves a state directory with dirs::state_dir(), falling back to dirs::cache_dir(). If neither can be determined, it fails with this error. The state dir holds runtime data like devel.toml.","triggerScenarios":"Calling Config::new() when both dirs::state_dir() (XDG_STATE_HOME + home resolution) and dirs::cache_dir() (XDG_CACHE_HOME + home) return None, i.e. no resolvable user home.","commonSituations":"Running paru under systemd timers/services with a minimal environment; containers or chroots without HOME; XDG_STATE_HOME and XDG_CACHE_HOME both unset AND HOME unset/unreadable.","solutions":["Set HOME to a writable directory before running paru.","Set XDG_STATE_HOME (e.g. $HOME/.local/state) or XDG_CACHE_HOME so one resolver succeeds.","Verify the runtime user has a valid home directory in the user database.","As a last resort in containers, create /home/user, set HOME, and run as that user."],"exampleFix":"# before (systemd service)\n[Service]\nExecStart=/usr/bin/paru -Syu\n# after\n[Service]\nEnvironment=HOME=/home/build\nEnvironment=XDG_STATE_HOME=/home/build/.local/state\nExecStart=/usr/bin/paru -Syu","handlingStrategy":"validation","validationCode":"if dirs::state_dir().is_none() && dirs::cache_dir().is_none() {\n    eprintln!(\"set XDG_STATE_HOME or XDG_CACHE_HOME (and HOME) before running\");\n    std::process::exit(1);\n}","typeGuard":"fn has_state_dir() -> bool { dirs::state_dir().or_else(dirs::cache_dir).is_some() }","tryCatchPattern":null,"preventionTips":["Set XDG_STATE_HOME in systemd units via Environment=.","Ensure the runtime user has a valid home directory.","Run containers as a non-root user with a defined HOME."],"tags":["config","environment","xdg"],"backgroundTag":"missing-env-var","analyzedSha":"9ac3578807a87858651e81a02586ceb947686e7c","analyzedAt":"2026-09-12T04:57:59.861Z","contentChangedAt":"2026-09-12T04:57:59.861Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}