rust-lang/cargo · error

must be a host tuple

Error message

must be a host tuple

What it means

`explicit_host_kind` builds a `CompileTarget` from the host triple string via `CompileTarget::new(host, false).expect("must be a host tuple")`. The `host` value comes from `bcx.host_triple()`, which Cargo obtained from `rustc -vV` and already validated as a real target tuple during target-data init. Re-parsing it must therefore succeed. Failure indicates the cached host triple is no longer parseable — typically a toolchain/sysroot change mid-build.

Source

Thrown at src/compiler/compilation.rs:605

        .filter_map(|(key, cfg)| cfg.linker.as_ref().map(|linker| (key, linker)))
        .filter(|(key, _linker)| CfgExpr::matches_key(key, target_cfg));
    let matching_linker = cfgs.next();
    if let Some((key, linker)) = cfgs.next() {
        anyhow::bail!(
            "several matching instances of `target.'cfg(..)'.linker` in configurations\n\
             first match `{}` located in {}\n\
             second match `{}` located in {}",
            matching_linker.unwrap().0,
            matching_linker.unwrap().1.definition,
            key,
            linker.definition
        );
    }
    Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(bcx.gctx)))
}

fn explicit_host_kind(host: &str) -> CompileKind {
    let target = CompileTarget::new(host, false).expect("must be a host tuple");
    CompileKind::Target(target)
}

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Pin the toolchain with `rust-toolchain.toml` and restart the build.
  2. Avoid changing `RUSTUP_TOOLCHAIN`/`RUSTC` while Cargo runs.
  3. Run `cargo clean` after a toolchain change.

Example fix

// before
let target = CompileTarget::new(host, false).expect("must be a host tuple");
// after
let target = CompileTarget::new(host, false).with_context(|| format!("host triple `{host}` is no longer parseable; did the toolchain change?"))?;
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the host triple is parseable by the active rustc before relying on target-applies-to-host=false
use std::process::Command;
fn host_triple_valid(host: &str) -> bool {
    Command::new("rustc").args(["--print", "target-list"]).output()
        .map(|o| String::from_utf8_lossy(&o.stdout).lines().any(|l| l == host)).unwrap_or(false)
}

Prevention

When it happens

Trigger: `target-applies-to-host = false` combined with a host triple that the current rustc can no longer parse (e.g. rustc was swapped to one lacking that target); the rustc host tuple changed between `BuildContext` construction and the call to `target_runner`/`host_linker`.

Common situations: Concurrent `rustup` toolchain switch during a build; `RUSTUP_TOOLCHAIN` rewritten between Cargo sub-processes; `host` value stale across a Cargo-as-library long-lived `BuildContext`.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/d6979f7e791fc558.json. Report an issue: GitHub.