xai-org/grok-build · error

no user grok home (set $GROK_HOME or $HOME)

Error message

no user grok home (set $GROK_HOME or $HOME)

What it means

default_auth_path resolves the directory holding the user's grok credentials by calling xai_grok_config::user_grok_home(), which reads $GROK_HOME (falling back to $HOME). If neither environment variable is set/resolvable, this error is thrown instead of guessing a path.

Source

Thrown at crates/codegen/xai-grok-workspace/src/hub_auth/mod.rs:88

    #[serde(default)]
    user_id: String,
    #[serde(default)]
    refresh_token: Option<String>,
    #[serde(default)]
    oidc_issuer: Option<String>,
    #[serde(default)]
    oidc_client_id: Option<String>,
    #[serde(default)]
    principal_type: Option<String>,
    #[serde(default)]
    principal_id: Option<String>,
    #[serde(default)]
    expires_at: Option<chrono::DateTime<chrono::Utc>>,
}

pub fn default_auth_path() -> anyhow::Result<PathBuf> {
    let grok = xai_grok_config::user_grok_home()
        .ok_or_else(|| anyhow::anyhow!("no user grok home (set $GROK_HOME or $HOME)"))?;
    Ok(grok.join("auth.json"))
}

/// Read the active OIDC entry and its scope key. The key is threaded to the
/// refresh write so rotation updates exactly the entry that was read.
///
/// When several OIDC entries qualify, pick the **latest `expires_at`** — the
/// entry the shell is actively refreshing. The previous first-key selection
/// was alphabetical and could rotate a *different principal's* RT chain than
/// the one the user's sessions use.
fn read_auth_entry(path: &Path) -> anyhow::Result<(String, AuthEntry)> {
    if !path.exists() {
        anyhow::bail!(
            "No auth credentials found at {}. Run `grok login` first.",
            path.display()
        );
    }

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Set the HOME environment variable for the process/user running the tool.
  2. Set GROK_HOME explicitly to the directory containing auth.json.
  3. In Docker, add `ENV HOME=/root` or run with `-e HOME=...`.
  4. In systemd units, add `Environment=HOME=%h` to the [Service] section.

Example fix

// before: no home in container
CMD ["grok", "serve"]
// after
ENV HOME=/root
CMD ["grok", "serve"]
# or: docker run -e GROK_HOME=/data/grok ...
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_grok_home_configured() -> Result<(), String> {
    if std::env::var_os("GROK_HOME").is_some() || std::env::var_os("HOME").is_some() {
        Ok(())
    } else {
        Err("set $GROK_HOME or $HOME before running".into())
    }
}

Try / catch

match default_auth_path() {
    Ok(p) => p,
    Err(e) if e.to_string().contains("no user grok home") => {
        eprintln!("set GROK_HOME or HOME and retry");
        std::process::exit(2);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling default_auth_path (or `provider()`, which uses it) in an environment where both GROK_HOME and HOME are unset — e.g. systemd services with a scrubbed environment, Docker containers without HOME, or CI jobs running as a user without a home directory.

Common situations: Docker images running as non-root without ENV HOME set; systemd unit files lacking Environment=HOME=; CI runners with minimal env; running the tool via a wrapper that strips environment variables.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/1dd5f359c3156fe0. Report an issue: GitHub.