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
- Set the HOME environment variable for the process/user running the tool.
- Set GROK_HOME explicitly to the directory containing auth.json.
- In Docker, add `ENV HOME=/root` or run with `-e HOME=...`.
- 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
- Always set HOME in Dockerfiles (ENV HOME=/root) and systemd units (Environment=HOME=%h)
- Prefer explicit GROK_HOME in service/container deployments
- Check env vars in startup/health scripts before first auth call
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
- failed to parse {}: {e}
- no OIDC auth entry found in {}. Run `grok login` first.
- auth entry has no oidc_issuer — cannot refresh expired token
- auth entry has no oidc_client_id — cannot refresh expired to
- Session does not exist locally (session registry is disabled
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/1dd5f359c3156fe0.
Report an issue: GitHub.