Morganamilo/paru · error · anyhow::Error

duplicate packages

Error message

duplicate packages: {}

What it means

check_actions (called from prepare_build) computes duplicate_targets() from the Actions struct; if the same package name appears more than once among install targets, it fails listing the duplicates. This prevents pacman/makepkg from receiving conflicting repeated targets.

Solutions

  1. Remove the repeated package name from the command line or target list
  2. Deduplicate targets before invoking paru: paru -S $(echo pkg pkg | tr ' ' '\n' | sort -u)
  3. If triggered by a PKGBUILD, rename conflicting split-package entries so pkgname values are unique

Example fix

// before
paru -S linux linux
// after
paru -S linux
Defensive patterns

Strategy: validation

Validate before calling

// dedupe targets before invoking paru
let targets: Vec<String> = args.targets.clone();
let unique: std::collections::HashSet<_> = targets.iter().collect();
assert_eq!(unique.len(), targets.len(), "duplicate targets: remove repeats");

Prevention

When it happens

Trigger: Installing a command line like `paru -S pkg pkg` or a package both explicitly and as part of a group/PKGBUILD target set so duplicate_targets() returns non-empty.

Common situations: Shell loops or aliases appending a package already listed; combining -S targets with a PKGBUILD whose pkgname list overlaps the CLI targets.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of Morganamilo/paru@9ac3578807 (2026-09-12). Data as JSON: /api/errors/59eff00716d0e072. Report an issue: GitHub.

Appendix: source

Thrown at src/install.rs:1347

    warnings.all(config.color, config.cols);
}

fn fmt_stack(want: &DepMissing) -> String {
    match &want.dep {
        Some(dep) => format!("{} ({})", want.pkg, dep),
        None => want.pkg.to_string(),
    }
}

fn check_actions(
    config: &Config,
    actions: &mut Actions,
    install_targets: bool,
) -> Result<(Vec<Conflict>, Vec<Conflict>)> {
    let c = config.color;
    let dups = actions.duplicate_targets();
    ensure!(
        dups.is_empty(),
        tr!("duplicate packages: {}", dups.join(" "))
    );

    if !actions.missing.is_empty() {
        let mut err = tr!("could not find all required packages:");
        for missing in &actions.missing {
            if missing.stack.is_empty() {
                write!(err, "\n    {} (target)", c.error.paint(&missing.dep))?;
            } else {
                let stack = missing
                    .stack
                    .iter()
                    .map(fmt_stack)
                    .collect::<Vec<_>>()
                    .join(" -> ");
                err.push_str(&tr!(
                    "\n    {missing} (wanted by: {stack})",

View on GitHub (pinned to 9ac3578807)