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
- 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.
- 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.
- 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.
- 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
- Pin one toolchain per workspace with rust-toolchain.toml so cargo and rustc never diverge.
- Never swap rustc versions (rustup update) while builds or IDE build daemons are running; restart the IDE/rust-analyzer afterwards.
- Validate custom target JSON specs with `rustc --print file-names --crate-type bin --target spec.json` before wiring them into CI.
- After toolchain changes, `cargo clean` (or delete target/) to purge caches built by the previous rustc.
- For cargo-as-a-library code, treat internal `.expect()`s as bugs to report — capture `RUST_BACKTRACE=1` output when they fire.
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
- artifact-dir was not locked during clean
- malformed output when learning about crate-type
- output of --print= missing when learning about…
- argument for --color must be auto, always, or never, but…
- argument for --color must be auto, always, or never, but…
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)