rust-lang/cargo · critical

target must support `bin`

Error message

target must support `bin`

What it means

This is an internal Cargo assertion (a panic, not a returned error) inside `CompilationFiles::bin_link_for_target`, which computes the uplifted output path for a binary target when no Unit is available. Line 424 unwraps the Result of `TargetInfo::rustc_outputs(CompileMode::Build, &TargetKind::Bin, triple)`, which shells out to rustc to learn what file type rustc emits for a `bin` crate. The panic means Cargo could not successfully query (or parse the output of) rustc for the bin file type of the active compile target — an invariant Cargo assumes always holds for bin targets.

Solutions

  1. Verify the toolchain is intact: `rustup update` (or reinstall the toolchain), then retry `cargo build` in a trivial bin crate on the same triple to isolate the failure.
  2. If using a custom target spec, confirm rustc itself can answer the bin query: `rustc --print file-names --crate-type bin --target my-target.json empty.rs` — if that errors, fix the JSON spec or use a target whose spec supports bins.
  3. Ensure cargo and rustc come from the same toolchain (`rustup which cargo`, `rustup which rustc`) and that no stale `.fingerprint`/target-info cache from an older rustc is being reused — `cargo clean` or `rm -rf target` removes it.
  4. If the panic reproduces on a healthy toolchain with a stock target, it is a Cargo bug: report it to https://github.com/rust-lang/cargo/issues with the repro, cargo/rustc versions (`cargo version --verbose`), and full backtrace (`RUST_BACKTRACE=1 cargo build`).

Example fix

# before: panic on a custom target
rustup run mytoolchain cargo build --target boards/my-target.json
#   -> `target must support `bin``

# after: prove rustc can report bin outputs for this spec, then build
rustc --print file-names --crate-type bin --target boards/my-target.json /dev/null
cargo build --target boards/my-target.json
Defensive patterns

Strategy: validation

Validate before calling

# Before building, prove rustc can discover bin outputs for the exact toolchain+triple:
rustc --print file-names --crate-type bin --target "$TRIPLE" empty.rs \
  || echo "ERROR: rustc cannot report bin file types for $TRIPLE — fix toolchain/spec first"
# And confirm cargo/rustc come from the same toolchain:
[ "$(dirname "$(rustup which cargo)")" = "$(dirname "$(rustup which rustc)")" ] \
  || echo "ERROR: cargo and rustc are from different toolchains"

Type guard

// For callers embedding cargo as a library: narrow before asking for bin paths.
fn as_bin_target<'a>(target: &'a cargo::core::Target) -> Option<&'a cargo::core::Target> {
    target.is_bin().then_some(target)
}
// Only pass targets that survived the guard to bin_link_for_target.

Prevention

When it happens

Trigger: Calling `cargo build`/`cargo run` (or the library API `bin_link_for_target`) where the rustc subprocess used to discover bin output file types fails or returns unparseable output: a broken or half-installed rustup toolchain, a rustc/cargo version mismatch, or a custom `--target my-spec.json` whose spec makes `rustc --print file-names --crate-type bin` fail. A sibling expect (no FileFlavor::Normal entry) covers the 'bin unsupported by target' case; line 424 specifically fires on the hard Err path (rustc query failure).

Common situations: Corrupt or mid-update rustup installations; swapping rustc versions while a build daemon/IDE keeps old target-info caches; custom bare-metal/wasm target JSON files that omit fields rustc's file-names query needs; mixing cargo from one toolchain with rustc from another (e.g., cargo-as-a-library embedding); rarely, a genuine Cargo regression where a non-bin-capable kind reaches this code path.

Related errors


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

Appendix: source

Thrown at src/compiler/build_runner/compilation_files.rs:430

    /// This should only to be used when a `Unit` is not available.
    pub fn bin_link_for_target(
        &self,
        target: &Target,
        kind: CompileKind,
        bcx: &BuildContext<'_, '_>,
    ) -> CargoResult<Option<PathBuf>> {
        assert!(target.is_bin());
        let Some(dest) = self.layout(kind).artifact_dir().map(|v| v.dest()) else {
            return Ok(None);
        };
        let info = bcx.target_data.info(kind);
        let (file_types, _) = info
            .rustc_outputs(
                CompileMode::Build,
                &TargetKind::Bin,
                bcx.target_data.short_name(&kind),
            )
            .expect("target must support `bin`");

        let file_type = file_types
            .iter()
            .find(|file_type| file_type.flavor == FileFlavor::Normal)
            .expect("target must support `bin`");

        Ok(Some(dest.join(file_type.uplift_filename(target))))
    }

    /// Returns the filenames that the given unit will generate.
    ///
    /// Note: It is not guaranteed that all of the files will be generated.
    pub(super) fn outputs(
        &self,
        unit: &Unit,
        bcx: &BuildContext<'a, 'gctx>,
    ) -> CargoResult<Arc<Vec<OutputFile>>> {
        self.outputs[unit]

View on GitHub (pinned to 42eee92bc9)