rust-lang/cargo · error

already loaded without errors

Error message

already loaded without errors

What it means

On the nightly-only shell-completion path in `cargo`'s `main`, `GlobalContext::default().expect("already loaded without errors")` constructs the global config a second time inside the `clap_complete::CompleteEnv` factory. It already succeeded once at the top of `main`, so the second call is expected to succeed too. The panic indicates a transient or environment-driven failure on the reload — config files changed between the two calls, a HOME/CARGO_HOME race, or filesystem error.

Source

Thrown at src/bin/cargo/main.rs:34

fn main() {
    let _guard = setup_logger();

    let mut gctx = match GlobalContext::default() {
        Ok(gctx) => gctx,
        Err(e) => {
            let mut shell = Shell::new();
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };

    let nightly_features_allowed = matches!(&*features::channel(), "nightly" | "dev");
    if nightly_features_allowed {
        let _span = tracing::span!(tracing::Level::TRACE, "completions").entered();
        let args = std::env::args_os();
        let current_dir = std::env::current_dir().ok();
        let completer = clap_complete::CompleteEnv::with_factory(|| {
            let mut gctx = GlobalContext::default().expect("already loaded without errors");
            cli::cli(&mut gctx)
        })
        .var("CARGO_COMPLETE");
        if completer
            .try_complete(args, current_dir.as_deref())
            .unwrap_or_else(|e| {
                let mut shell = Shell::new();
                cargo::exit_with_error(e.into(), &mut shell)
            })
        {
            return;
        }
    }

    let result = if let Some(lock_addr) = cargo::ops::fix_get_proxy_lock_addr() {
        cargo::ops::fix_exec_rustc(&gctx, &lock_addr).map_err(|e| CliError::from(e))
    } else {
        let _token = cargo::util::job::setup();

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Re-trigger completion after the config file write finishes.
  2. Ensure `HOME` and `CARGO_HOME` point to a stable, readable directory.
  3. Check permissions on `~/.cargo/config.toml` and the credentials file; `chmod u+r` if needed.
  4. If it reproduces, capture `RUST_LOG=cargo::util::context=trace` output and file a Cargo bug — the second load should arguably fall back rather than panic.

Example fix

// before
let mut gctx = GlobalContext::default().expect("already loaded without errors");
// after (fail soft inside the non-critical completion path)
let mut gctx = match GlobalContext::default() {
    Ok(g) => g,
    Err(e) => {
        tracing::warn!("completion config reload failed: {e}");
        return;
    }
};
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate that the cargo config is readable before relying on completion:
use std::process::Command;
fn cargo_config_ok() -> bool {
    Command::new("cargo").arg("--version").output().map(|o| o.status.success()).unwrap_or(false)
}

Try / catch

// Wrap your cargo invocation; on panic/non-zero exit from completion, fall back to no completion
let out = std::process::Command::new("cargo").args(args).status();
match out {
    Ok(s) if s.success() => {}
    _ => { /* silently skip completion */ }
}

Prevention

When it happens

Trigger: Triggering tab-completion (`CARGO_COMPLETE` env) on a nightly/dev Cargo while the config files (`~/.cargo/config.toml`, `$CARGO_HOME/config.toml`, or a credential file) are concurrently modified or become unreadable; HOME unset/unwritable mid-completion; permission flip on the config between the two `GlobalContext::default()` calls.

Common situations: Shell completion triggered while a package manager or editor rewrites `~/.cargo/config.toml`; running under a sandbox/CI that mutates `$HOME`; concurrent `cargo login`/`cargo logout` rewriting the credentials file.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/6e4d49113e7faded.json. Report an issue: GitHub.