Morganamilo/paru · error
{}:{}: {}
Error message
{}:{}: {} What it means
This is a wrapper error: when parsing a config file (paru.conf or an Include-ed file) fails, paru attaches the filename and line number of the offending directive/callback to the underlying parse error via anyhow! and map_err. It tells the developer exactly which file and line caused the config parse failure. The original error message is preserved as the source of the anyhow chain.
Solutions
- Read the error's filename:line part and fix the offending line in that file
- Check the option name and value against paru's supported directives (paru.conf man page / PARU_CONF docs)
- Restore a known-good paru.conf (e.g. /usr/share/doc/paru/paru.conf example)
- Use paru --paruconf <path> to test an alternate config file in isolation
Example fix
// before (paru.conf) BottomUp = maybe // after (paru.conf) BottomUp = true
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate each non-empty, non-comment line of paru.conf has form key = value
let bad: Vec<&str> = conf.lines().filter(|l| !l.trim().is_empty() && !l.trim().starts_with('#') && !l.contains('=') && !l.trim().starts_with('[') && !l.starts_with("Include")).collect();
if !bad.is_empty() { eprintln!("malformed lines: {:?}", bad); } Try / catch
match Config::new() {
Ok(c) => c,
Err(e) => { eprintln!("paru config error: {:?}", e); std::process::exit(1); }
} Prevention
- Copy the shipped example paru.conf and change one option at a time
- Check each edited option against the paru.conf man page
- Keep a version-controlled copy of paru.conf to diff against
When it happens
Trigger: Any parse_directive / parse call inside config file parsing that returns Err; the error is mapped at src/config.rs:574 into '{filename}:{line_number}: {e}'. Triggered by any malformed key=value line or unknown directive in paru.conf or an included config file.
Common situations: Typo in a paru.conf option name (e.g. 'BottomUp' vs 'bottomup'), invalid value for an enum-like option, malformed Include file lines, or editing paru.conf by hand and breaking syntax.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- invalid value ' ' for key ' ', expected
- no local repos configured, add one to your pacman.conf: …
- option must be a number
- unknown mode
- section can not be called
AI-assisted analysis of Morganamilo/paru@9ac3578807 (2026-09-12).
Data as JSON: /api/errors/b74a3d8f262961b9.
Report an issue: GitHub.
Appendix: source
Thrown at src/config.rs:574
let err = match cb.kind {
CallbackKind::Section(section) => {
self.section = Some(section.to_string());
if !matches!(section, "options" | "bin" | "env")
&& self.pkgbuild_repos.repo(section).is_none()
{
if matches!(section, "local" | "aur" | "pkg" | "base") || section.contains('.')
{
bail!(tr!("section can not be called {}", section));
}
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");View on GitHub (pinned to 9ac3578807)