{"id":"5a4c410475cd17bf","repo":"rust-lang/cargo","slug":"probably-rustup-rustc-but-without-rustup-s-env-va","errorCode":null,"errorMessage":"probably rustup rustc, but without rustup's env vars","messagePattern":"probably rustup rustc, but without rustup's env vars","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/util/rustc.rs","lineNumber":394,"sourceCode":"    let maybe_rustup = rustup_rustc == rustc;\n    match (\n        maybe_rustup,\n        gctx.get_env(\"RUSTUP_HOME\"),\n        gctx.get_env(\"RUSTUP_TOOLCHAIN\"),\n    ) {\n        (_, Ok(rustup_home), Ok(rustup_toolchain)) => {\n            debug!(\"adding rustup info to rustc fingerprint\");\n            rustup_toolchain.hash(&mut hasher);\n            rustup_home.hash(&mut hasher);\n            let real_rustc = Path::new(&rustup_home)\n                .join(\"toolchains\")\n                .join(rustup_toolchain)\n                .join(\"bin\")\n                .join(\"rustc\")\n                .with_extension(env::consts::EXE_EXTENSION);\n            paths::mtime(&real_rustc)?.hash(&mut hasher);\n        }\n        (true, _, _) => anyhow::bail!(\"probably rustup rustc, but without rustup's env vars\"),\n        _ => (),\n    }\n\n    Ok(Hasher::finish(&hasher))\n}\n\nfn process_fingerprint(cmd: &ProcessBuilder, extra_fingerprint: u64) -> u64 {\n    let mut hasher = StableHasher::new();\n    extra_fingerprint.hash(&mut hasher);\n    cmd.get_args().for_each(|arg| arg.hash(&mut hasher));\n    let mut env = cmd.get_envs().iter().collect::<Vec<_>>();\n    env.sort_unstable();\n    env.hash(&mut hasher);\n    Hasher::finish(&hasher)\n}\n","sourceCodeStart":376,"sourceCodeEnd":410,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/util/rustc.rs#L376-L410","documentation":"rustc_fingerprint detects that the resolved rustc path equals the rustup shim path (`maybe_rustup` true), meaning the compiler appears to be rustup-managed, but neither `RUSTUP_HOME` nor `RUSTUP_TOOLCHAIN` is set in the environment. Because rustup can swap the real compiler without touching the shim, Cargo cannot reliably fingerprint it without those vars, so it conservatively bails rather than risk a stale cache.","triggerScenarios":"Invoking cargo with a rustup-managed rustc on PATH but with rustup's env vars stripped — e.g. running under a sanitized/wrapper environment, a container that cleared env, calling the rustup shim directly without rustup's exported vars, or an IDE/launcher that filtered the environment.","commonSituations":"Containers/CI images that strip env vars but keep the rustup shim; `env -i` style sanitized runs; a custom launcher that invokes cargo without forwarding rustup's env; rustup installed but invoked through a proxy that drops env.","solutions":["Ensure `RUSTUP_HOME` and `RUSTUP_TOOLCHAIN` are set/forwarded in the environment (rustup normally exports them; run `rustup which rustc` to see expected values).","Invoke cargo through rustup's normal entrypoint so env is populated, rather than calling the shim directly.","Pin a direct (non-rustup) rustc via `build.rustc` in config.toml if you must run with a stripped environment.","Re-run `rustup default <toolchain>` to repair the rustup setup."],"exampleFix":"# before (env stripped)\nenv -i cargo build\n\n# after (forward rustup env)\nexport RUSTUP_HOME=\"$(rustup show home)\"\nexport RUSTUP_TOOLCHAIN=\"$(rustup show | awk '/Default Toolchain/{print $2}')\"\ncargo build","handlingStrategy":"fallback","validationCode":"fn rustup_env_present() -> bool {\n    std::env::var(\"RUSTUP_HOME\").is_ok() && std::env::var(\"RUSTUP_TOOLCHAIN\").is_ok()\n}\n// if false, either forward the env or pin build.rustc to a direct binary","typeGuard":"fn looks_like_rustup_rustc(rustc: &std::path::Path, rustup_rustc: &std::path::Path) -> bool {\n    rustc == rustup_rustc\n}","tryCatchPattern":"// Fallback: if fingerprinting bails on rustup env, re-run with env forwarded\n// or pin a non-rustup rustc.\nmatch rustc_fingerprint(...) {\n    Err(e) if e.to_string().contains(\"without rustup's env vars\") => {\n        std::env::set_var(\"RUSTUP_HOME\", home);\n        std::env::set_var(\"RUSTUP_TOOLCHAIN\", tc);\n        // retry\n    }\n    r => r,\n}","preventionTips":["Always forward `RUSTUP_HOME` and `RUSTUP_TOOLCHAIN` in containers/wrappers.","Invoke cargo through the normal rustup entrypoint, not the bare shim.","In sanitized envs, pin `build.rustc` to a direct (non-shim) binary."],"tags":["rustc","rustup","environment","toolchain","fingerprint"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}