Morganamilo/paru · error · anyhow::Error
failed to find config directory
Error message
failed to find config directory
What it means
paru's Config::new() resolves the user's XDG config directory via the `dirs` crate (dirs::config_dir()) and appends "paru" to it. If no config directory can be determined (e.g. $XDG_CONFIG_HOME unset and no home directory resolvable), it returns this anyhow error instead of constructing a Config.
Solutions
- Set HOME to the user's home directory before invoking paru.
- Set XDG_CONFIG_HOME explicitly (e.g. XDG_CONFIG_HOME=$HOME/.config).
- Check that the invoking user exists in /etc/passwd with a valid home directory.
- If embedding paru as a library, ensure dirs::config_dir() prerequisites are met before calling Config::new().
Example fix
// before (container CMD)
CMD ["paru", "-Syu"]
// after
CMD ["sh", "-c", "export HOME=${HOME:-/root} XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config} && exec paru -Syu"] Defensive patterns
Strategy: validation
Validate before calling
if std::env::var("HOME").is_err() && std::env::var("XDG_CONFIG_HOME").is_err() {
std::env::set_var("XDG_CONFIG_HOME", "/root/.config"); // or fail fast with a clear message
}
assert!(dirs::config_dir().is_some(), "no config dir resolvable"); Type guard
fn has_config_dir() -> bool { dirs::config_dir().is_some() } Prevention
- Always export HOME in service units, cron jobs, and containers.
- Set XDG_CONFIG_HOME explicitly in minimal environments.
- Smoke-test CLI tools under `env -i` to catch missing env dependencies early.
When it happens
Trigger: Calling Config::new() (directly or via paru startup) when dirs::config_dir() returns None — typically because HOME is unset, the passwd entry lacks a home dir, or running in a stripped environment (cron, systemd service, containers).
Common situations: Running paru from a systemd unit, CI job, or Docker container without HOME/XDG_CONFIG_HOME set; running as a user with a malformed /etc/passwd entry; musl/minimal chroot environments.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- failed to find state directory
- failed to find cache directory
- config file ' ' does not exist
- invalid value ' ' for key ' ', expected
- unknown mode
AI-assisted analysis of Morganamilo/paru@9ac3578807 (2026-09-12).
Data as JSON: /api/errors/ea0fda79dd143293.
Report an issue: GitHub.
Appendix: source
Thrown at src/config.rs:584
self.pkgbuild_repos.add_repo(section.to_string());
}
Ok(())
}
CallbackKind::Directive(_, key, value) => self.parse_directive(key, value),
};
let filename = cb.filename.unwrap_or("paru.conf");
err.map_err(|e| anyhow!("{}:{}: {}", filename, cb.line_number, e))
}
}
impl Config {
pub fn new() -> Result<Self> {
let cache =
dirs::cache_dir().ok_or_else(|| anyhow!(tr!("failed to find cache directory")))?;
let cache = cache.join("paru");
let config =
dirs::config_dir().ok_or_else(|| anyhow!(tr!("failed to find config directory")))?;
let config = config.join("paru");
let state = dirs::state_dir()
.or_else(dirs::cache_dir)
.ok_or_else(|| anyhow!(tr!("failed to find state directory")))?;
let state = state.join("paru");
let build_dir = cache.join("clone");
let old_old_devel_path = cache.join("devel.json");
let old_devel_path = state.join("devel.json");
let devel_path = state.join("devel.toml");
let config_path = config.join("paru.conf");
let old = if old_devel_path.exists() {
Some(&old_devel_path)
} else if old_old_devel_path.exists() {
Some(&old_old_devel_path)
} else {
NoneView on GitHub (pinned to 9ac3578807)