xai-org/grok-build · error

NotFound

NotFound

Error message

no grok home

What it means

`write_persisted` persists the dashboard state to `~/.grok/config.toml`. It first resolves the config path via `config_path()`, which returns `None` when the user's home directory (the 'grok home') cannot be determined. In that case it throws `std::io::Error` with kind `NotFound` and message 'no grok home' instead of writing to an arbitrary location.

Source

Thrown at crates/codegen/xai-grok-pager/src/views/dashboard/state.rs:4334

        enabled,
        grouping,
        pinned,
        reorder,
    })
}

/// Synchronous, blocking write of the persisted dashboard config.
/// Spawned from [`crate::app::actions::Effect`] handlers via `spawn_blocking`.
///
/// Short-circuits when `read_config_document_for_edit` returns `None`.
/// That helper returns `None` only when the file is non-empty AND unparseable, meaning we
/// MUST NOT overwrite it (the file may contain user data we cannot interpret).
/// Without this guard, a single dashboard pin would clobber every other table in `~/.grok/config.toml` (`[ui]`, `[hints]`, `[mcpServers]`, …).
///
/// Atomic write via `<path>.dashboard.tmp.<pid>` then rename, so concurrent readers never observe a half-truncated file.
pub fn write_persisted(p: &PersistedDashboard) -> std::io::Result<()> {
    let path = config_path()
        .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::NotFound, "no grok home"))?;
    write_persisted_to_path(&path, p)
}

/// Path-taking variant of [`write_persisted`] so the on-disk round-trip can be exercised in tests against a `tempfile::TempDir`.
pub fn write_persisted_to_path(
    path: &std::path::Path,
    p: &PersistedDashboard,
) -> std::io::Result<()> {
    if let Some(parent) = path.parent() {
        std::fs::create_dir_all(parent)?;
    }
    let mut doc = match crate::config_toml_edit::read_config_document_for_edit(path) {
        Some(d) => d,
        None => {
            // File exists but is unparseable
            // Refuse to overwrite; doing so would erase every other table
            tracing::warn!(
                path = %path.display(),

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Set the `HOME` environment variable to an existing writable directory before running the tool
  2. Run as a user that has a valid home directory (check with `echo $HOME` / `getent passwd <user>`)
  3. In embedded/service contexts, pre-create the home dir and export `HOME=/path/to/it` in the unit/service env
  4. If you cannot set HOME, avoid persisting dashboard pins and handle the io::Error kind NotFound gracefully

Example fix

// before
sudo -u serviceuser grok dashboard   # HOME unset -> error
// after
sudo -u serviceuser env HOME=/home/serviceuser grok dashboard
Defensive patterns

Strategy: validation

Validate before calling

if std::env::var_os("HOME").is_none() {
    eprintln!("HOME is not set; dashboard persistence will fail");
    std::process::exit(1);
}

Try / catch

match write_persisted(&dash) {
    Err(e) if e.kind() == std::io::ErrorKind::NotFound && e.to_string().contains("no grok home") => {
        eprintln!("Cannot persist dashboard: set $HOME");
    }
    Err(e) => return Err(e.into()),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: Calling `write_persisted` (e.g. when a user pins a table on the dashboard) while the `HOME` environment variable is unset (or the platform home-dir lookup fails), so `config_path()` returns `None`.

Common situations: Running the CLI in a container, cron job, systemd unit, or SSH session where `HOME` is not set; running under a service account with no home directory; sanitizing env vars in tests/CI which strips `HOME`.

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/7ffda7ce27c2112a. Report an issue: GitHub.