rust-lang/cargo · critical · anyhow::Error

Cargo couldn't find your home directory. This probably…

Error message

Cargo couldn't find your home directory. This probably means that $HOME was not set.

What it means

`GlobalContext::default()` could not determine the user's home directory (`homedir(&cwd)` returned `None`). Cargo needs `$HOME` (or the OS equivalent) to locate `~/.cargo` for registries, caches, and global config, so it bails early with this hint.

Solutions

  1. Export `HOME` (or `USERPROFILE` on Windows) before invoking cargo: `export HOME=/tmp`.
  2. Set `CARGO_HOME` to an explicit writable path which removes the dependency on `$HOME`.
  3. Ensure the running user has a valid passwd entry (`getent passwd <user>`).
  4. In containers, do not use `env -i` without re-exporting `HOME`.

Example fix

// before (Dockerfile)
RUN env -i cargo build --release

// after
ENV HOME=/tmp
ENV CARGO_HOME=/tmp/cargo
RUN cargo build --release
Defensive patterns

Strategy: validation

Validate before calling

fn home_or_cargo_home_set() -> bool {
    std::env::var_os("HOME").or(std::env::var_os("USERPROFILE")).or(std::env::var_os("CARGO_HOME")).is_some()
}

Type guard

null

Try / catch

match GlobalContext::default() {
    Err(e) if e.to_string().contains("home directory") => { std::env::set_var("HOME", "/tmp"); GlobalContext::default()? }
    r => r?,
}

Prevention

When it happens

Trigger: Running cargo in an environment where neither `HOME`, nor platform-specific APIs (Windows `USERPROFILE`, etc.) resolve to a writable directory; running as a user with no passwd entry; minimal containers that clear the environment.

Common situations: Docker images that `env -i` and forget to set `HOME`; systemd services without `Environment=HOME=...`; chroot/nobody-user contexts; CI runners that strip env.

Related errors


AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11). Data as JSON: /api/errors/23e4146df44b8194. Report an issue: GitHub.

Appendix: source

Thrown at src/context/mod.rs:424

            progress_config: ProgressConfig::default(),
            env_config: Default::default(),
            nightly_features_allowed: matches!(&*features::channel(), "nightly" | "dev"),
            ws_roots: Default::default(),
            global_cache_tracker: Default::default(),
            deferred_global_last_use: Default::default(),
        }
    }

    /// Creates a new instance, with all default settings.
    ///
    /// This does only minimal initialization. In particular, it does not load
    /// any config files from disk. Those will be loaded lazily as-needed.
    pub fn default() -> CargoResult<GlobalContext> {
        let shell = Shell::new();
        let cwd =
            env::current_dir().context("couldn't get the current directory of the process")?;
        let homedir = homedir(&cwd).ok_or_else(|| {
            anyhow!(
                "Cargo couldn't find your home directory. \
                 This probably means that $HOME was not set."
            )
        })?;
        Ok(GlobalContext::new(shell, cwd, homedir))
    }

    /// Gets the user's Cargo home directory (OS-dependent).
    pub fn home(&self) -> &Filesystem {
        &self.home_path
    }

    /// Returns a path to display to the user with the location of their home
    /// config file (to only be used for displaying a diagnostics suggestion,
    /// such as recommending where to add a config value).
    pub fn diagnostic_home_config(&self) -> String {
        let home = self.home_path.as_path_unlocked();
        let path = match self.get_file_path(home, "config", false) {

View on GitHub (pinned to 98a09e7e7d)