rust-lang/rust · critical

Failed to spawn rustc: {}

Error message

Failed to spawn rustc: {}

What it means

Panics in the rustc-clif launcher shim when Command::exec() cannot replace the process with rustc. rustc-clif prepends the cranelift codegen-backend and sysroot flags and then execs the real rustc; the panic fires only when exec itself fails, not when rustc exits non-zero.

Source

Thrown at compiler/rustc_codegen_cranelift/scripts/rustc-clif.rs:54

        args.push(OsString::from(sysroot.to_str().unwrap()));
    }
    if passed_args.is_empty() {
        // Don't pass any arguments when the user didn't pass any arguments
        // either to ensure the help message is shown.
        args.clear();
    }
    args.extend(passed_args);

    let rustc = if let Some(rustc) = option_env!("RUSTC") {
        rustc
    } else {
        // Ensure that the right toolchain is used
        env::set_var("RUSTUP_TOOLCHAIN", option_env!("TOOLCHAIN_NAME").expect("TOOLCHAIN_NAME"));
        "rustc"
    };

    #[cfg(unix)]
    panic!("Failed to spawn rustc: {}", Command::new(rustc).args(args).exec());

    #[cfg(not(unix))]
    std::process::exit(
        Command::new(rustc).args(args).spawn().unwrap().wait().unwrap().code().unwrap_or(1),
    );
}

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Run `rustup toolchain list` and install the expected toolchain.
  2. Run `which rustc` / `$RUSTC --version` in the same environment.
  3. Invoke rustc-clif through the installed toolchain (e.g. `rustup run <toolchain> rustc-clif`) rather than the bare binary, so the sysroot resolves correctly.
  4. Re-run `./y.rs prepare` to (re)install the toolchain and scripts together.

Example fix

// before
#[cfg(unix)]
panic!("Failed to spawn rustc: {}", Command::new(rustc).args(args).exec());
// after
#[cfg(unix)]
{
    eprintln!("rustc-clif: exec rustc={:?} sysroot={:?}", rustc, sysroot);
    panic!("Failed to spawn rustc: {}", Command::new(rustc).args(args).exec());
}
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_tool(name: &str) -> Result<(), String> {
    if which::which(name).is_err() {
        return Err(format!("{} not found on PATH; run `rustup component add rustc` or fix PATH", name));
    }
    Ok(())
}
// call ensure_tool("rustc") before invoking rustc-clif

Type guard

fn rustc_available() -> bool {
    std::process::Command::new("rustc").arg("--version").status().is_ok()
}

Try / catch

use std::panic;
if panic::catch_unwind(|| Command::new("rustc").args(args).status()).is_err() {
    eprintln!("rustc spawn failed; check toolchain / PATH"); std::process::exit(1);
}

Prevention

When it happens

Trigger: Reached at the tail of rustc-clif.rs (unix path) after assembling -Zcodegen-backend=, --sysroot, and panic flags. Exec fails when the rustc binary cannot be started at all.

Common situations: rustc not on PATH or RUSTC env var points to a missing/unexecutable binary; the rustup toolchain named by TOOLCHAIN_NAME is not installed or was partially uninstalled; running rustc-clif directly without the rustup-managed sysroot next to it; broken PATH in a nested shell or CI container; the sysroot parent walk (sysroot.parent()) produced an unexpected path because the binary was relocated.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/4a477110a7574fad.json. Report an issue: GitHub.