rust-lang/cargo · error
$CARGO not set
Error message
$CARGO not set
What it means
cargo_exe (mod.rs:553-604) resolves the path to the running `cargo` binary. It tries current_exe() and argv[0] first; if neither yields a path whose file_stem is 'cargo', it falls back to the $CARGO environment variable. If $CARGO is also unset, it bails '$CARGO not set'. This fallback exists for cargo-as-library consumers, valgrind, ld.so, or cargo-* subcommand wrappers where current_exe/argv0 are not 'cargo'.
Source
Thrown at src/context/mod.rs:564
None
},
self,
)
}
/// Gets the path to the `cargo` executable.
pub fn cargo_exe(&self) -> CargoResult<&Path> {
self.cargo_exe
.try_borrow_with(|| {
let from_env = || -> CargoResult<PathBuf> {
// Try re-using the `cargo` set in the environment already. This allows
// commands that use Cargo as a library to inherit (via `cargo <subcommand>`)
// or set (by setting `$CARGO`) a correct path to `cargo` when the current exe
// is not actually cargo (e.g., `cargo-*` binaries, Valgrind, `ld.so`, etc.).
let exe = self
.get_env_os(crate::CARGO_ENV)
.map(PathBuf::from)
.ok_or_else(|| anyhow!("$CARGO not set"))?;
Ok(exe)
};
fn from_current_exe() -> CargoResult<PathBuf> {
// Try fetching the path to `cargo` using `env::current_exe()`.
// The method varies per operating system and might fail; in particular,
// it depends on `/proc` being mounted on Linux, and some environments
// (like containers or chroots) may not have that available.
let exe = env::current_exe()?;
Ok(exe)
}
fn from_argv() -> CargoResult<PathBuf> {
// Grab `argv[0]` and attempt to resolve it to an absolute path.
// If `argv[0]` has one component, it must have come from a `PATH` lookup,
// so probe `PATH` in that case.
// Otherwise, it has multiple components and is either:
// - a relative path (e.g., `./cargo`, `target/debug/cargo`), orView on GitHub (pinned to 0e07a15537)
Solutions
- Set `CARGO` to the absolute path of the cargo binary before invoking the process.
- Name the binary 'cargo' or invoke it through a normal PATH lookup so argv[0]/current_exe resolve correctly.
- Ensure /proc is mounted on Linux (current_exe depends on it).
Example fix
# before valgrind my-cargo-wrapper build # current_exe/argv0 obscured # after export CARGO=$(command -v cargo) valgrind my-cargo-wrapper build
Defensive patterns
Strategy: validation
Validate before calling
# For cargo-as-library or wrapper binaries, set CARGO explicitly:
export CARGO="${CARGO:-$(command -v cargo)}"
exec "$CARGO" "$@" Prevention
- Always set CARGO when invoking cargo through a launcher (valgrind, ld.so, wrapper).
- Name cargo-wrapper binaries distinctly and set CARGO rather than relying on argv[0].
- Ensure /proc is mounted on Linux so current_exe() works.
When it happens
Trigger: Using cargo as a library from a binary that is not named cargo, under a launcher (valgrind/ld.so/wrapper) that obscures argv[0] and current_exe, without setting $CARGO. Also when cargo needs to re-invoke itself (e.g. `cargo invoke`) but cannot locate its own binary.
Common situations: A custom cargo-* subcommand that links against the cargo crate; running cargo under valgrind or a dynamic linker; stripped/oddly-named binaries.
Related errors
- no argv[0]
- no executable for `{}` found in PATH
- no such file or subcommand `{cmd}`{is_dir}{suggested_command
- no such subcommand `{cmd}`{suggested_command}{suggested_scri
- {key:?} could not be found in the environment snapshot
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/f5c6af20b69d89a6.json.
Report an issue: GitHub.