rust-lang/cargo · error

several matching instances of `target.'cfg(..)'.runner` in…

Error message

several matching instances of `target.'cfg(..)'.runner` in configurations
first match `{}` located in {}
second match `{}` located in {}

What it means

Multiple `[target.'cfg(...)'.runner]` entries in configuration match the current target's cfg set, making the runner ambiguous. `CfgExpr::matches_key` returned true for two or more keys, so Cargo cannot pick one deterministically.

Solutions

  1. Consolidate runner config into a single source (e.g. only `.cargo/config.toml` or only env vars).
  2. Make cfg keys mutually exclusive (e.g. `cfg(all(target_os = "linux", not(target_env = "musl")))`).
  3. Delete the lower-priority matching entry identified in the error's `first match`/`second match` lines.
  4. Use a single wildcard `target.<triple>.runner` (exact triple) instead of cfg-based matching.

Example fix

// before (.cargo/config.toml)
[target.'cfg(unix)'.runner]
runner = "qemu-x86_64"
[target.'cfg(target_os = "linux")'.runner]
runner = "./run.sh"

// after
[target.x86_64-unknown-linux-gnu.runner]
runner = "./run.sh"
Defensive patterns

Strategy: validation

Validate before calling

fn count_matching_runner_cfgs(target_cfg: &[String], cfgs: &[(String, Runner)]) -> usize {
    cfgs.iter().filter(|(k, _)| cfg_matches(k, target_cfg)).count()
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Defining overlapping `target.'cfg(target_os = "linux")'.runner` and `target.'cfg(unix)'.runner` where both match; importing layered configs (user + project + env) that each set a runner for matching cfgs.

Common situations: Workspace merges inheriting multiple config sources; CI adding `CARGO_TARGET_*_RUNNER` alongside a config file runner; evolving cfg expressions to overlap accidentally.

Related errors


AI-assisted analysis of rust-lang/cargo@42eee92bc9 (2026-08-11). Data as JSON: /api/errors/6580d0bae007aeb3. Report an issue: GitHub.

Appendix: source

Thrown at src/compiler/compilation.rs:543

    // With `target-applies-to-host = true`,
    // host artifacts must fall through to pick up from [target]
    // since this is the stable behavior
    if kind.is_host() && !bcx.gctx.target_applies_to_host()? {
        return Ok(None);
    }

    // try target.'cfg(...)'.runner
    let target_cfg = bcx.target_data.info(kind).cfg();
    let mut cfgs = bcx
        .gctx
        .target_cfgs()?
        .iter()
        .filter_map(|(key, cfg)| cfg.runner.as_ref().map(|runner| (key, runner)))
        .filter(|(key, _runner)| CfgExpr::matches_key(key, target_cfg));
    let matching_runner = cfgs.next();
    if let Some((key, runner)) = cfgs.next() {
        anyhow::bail!(
            "several matching instances of `target.'cfg(..)'.runner` in configurations\n\
             first match `{}` located in {}\n\
             second match `{}` located in {}",
            matching_runner.unwrap().0,
            matching_runner.unwrap().1.definition,
            key,
            runner.definition
        );
    }
    Ok(matching_runner.map(|(_k, runner)| {
        (
            runner.val.path.clone().resolve_program(bcx.gctx),
            runner.val.args.clone(),
        )
    }))
}

/// Gets the user-specified linker for a particular host or target from the configuration.

View on GitHub (pinned to 42eee92bc9)