rust-lang/cargo · error · anyhow::Error
failed to connect to jobserver from environment variable
Error message
failed to connect to jobserver from environment variable `{name}={value:?}`: {e} What it means
Cargo tried to attach to an existing GNU make jobserver (semaphore-based parallelism via the `MAKEFLAGS`/`CARGO_MAKEFLAGS` env var) advertised in the environment, and the jobserver crate returned an error other than the benign `NoEnvVar`/`NoJobserver`/`NegativeFd`/`Unsupported`. The failing variable name, its raw value, and the underlying error are surfaced.
Solutions
- Unset the offending variable before invoking cargo: `unset MAKEFLAGS; cargo build`.
- Pass `--jobs N` to cargo explicitly to bypass the inherited jobserver.
- Ensure the parent `make` invocation actually creates the jobserver (`make -j4`, not `make`).
- Update the jobserver-providing tool (make 4.x, ninja) so the auth FDs are inheritable.
Example fix
// before make -j4 # Makefile rule: cargo build # inherits a jobserver FD that is closed -> error // after # Makefile build: +unset MAKEFLAGS; cargo build --jobs 4 # or build: +cargo build --jobs 4
Defensive patterns
Strategy: validation
Validate before calling
fn jobserver_env_valid() -> bool {
if let Ok(mf) = std::env::var("MAKEFLAGS") {
if mf.contains("--jobserver-auth=") {
// FDs must be open and inheritable; conservative check
return std::env::current_exe().is_ok();
}
}
true
} Type guard
null
Try / catch
match GlobalContext::load_jobserver() {
Err(e) if e.to_string().contains("failed to connect to jobserver") => { std::env::remove_var("MAKEFLAGS"); retry_without_jobserver()? }
r => r?,
} Prevention
- In Makefiles, prefix cargo recipes with `+` and unset `MAKEFLAGS` if unsure.
- Pass `--jobs N` explicitly when wrapping cargo.
- Don't forward `MAKEFLAGS` across process boundaries that close FDs.
When it happens
Trigger: Parent process exports a `MAKEFLAGS` containing a jobserver spec (`--jobserver-auth=<fds>`) but the file descriptors are invalid/closed; running under `make -jN` where the FDs were not inherited (e.g. cargo was exec'd after closing FDs); a stale `CARGO_MAKEFLAGS` from a previous make session.
Common situations: CI that wraps cargo in `make` and accidentally re-execs; containers that strip inherited FDs; custom build orchestrators that set `MAKEFLAGS` without providing live FDs; `make` older than 4.4 with incompatible auth syntax.
Related errors
- Cargo couldn't find your home directory. This probably…
- could not find cargo home dir
- could not parse ` `. Number of parallel jobs should be…
- does not exist, unable to build with the standard library…
- jobs may not be 0
AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11).
Data as JSON: /api/errors/a72153de3d1abd8b.
Report an issue: GitHub.
Appendix: source
Thrown at src/context/mod.rs:339
let jobserver::FromEnv { client, var } =
unsafe { jobserver::Client::from_env_ext(true) };
match client {
Ok(client) => return Ok(Some(client)),
Err(e)
if matches!(
e.kind(),
FromEnvErrorKind::NoEnvVar
| FromEnvErrorKind::NoJobserver
| FromEnvErrorKind::NegativeFd
| FromEnvErrorKind::Unsupported
) =>
{
Ok(None)
}
Err(e) => {
let (name, value) = var.unwrap();
Err(anyhow::anyhow!(
"failed to connect to jobserver from environment variable `{name}={value:?}`: {e}"
))
}
}
},
);
let jobserver = match &*GLOBAL_JOBSERVER {
Ok(jobserver) => jobserver.as_ref(),
Err(e) => {
let _ = shell.warn(e);
None
}
};
let env = Env::new();
let cache_key = "CARGO_CACHE_RUSTC_INFO";
let cache_rustc_info = match env.get_env_os(cache_key) {View on GitHub (pinned to 98a09e7e7d)