xai-org/grok-build · error

failed to read {}: {e}

Error message

failed to read {}: {e}

What it means

read_auth_entry loads the grok auth file (a JSON map of entries) from disk. If std::fs::read_to_string fails — the file cannot be read for any reason other than simply not existing (a missing file earlier produces a friendlier 'No auth credentials found' message) — this error wraps the path and the io error. This typically means the file exists but is inaccessible.

Source

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

}

/// 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()
        );
    }

    let content = std::fs::read_to_string(path)
        .map_err(|e| anyhow::anyhow!("failed to read {}: {e}", path.display()))?;
    let entries: BTreeMap<String, AuthEntry> = serde_json::from_str(&content)
        .map_err(|e| anyhow::anyhow!("failed to parse {}: {e}", path.display()))?;

    entries
        .into_iter()
        .filter(|(_, e)| e.refresh_token.is_some() && e.oidc_issuer.is_some())
        // Strictly-greater comparison: ties (including all-`None`) keep the
        // first candidate in BTreeMap (alphabetical) order, so single-entry
        // and legacy no-`expires_at` files behave exactly as before.
        .fold(None::<(String, AuthEntry)>, |best, cand| match best {
            Some(b) if cand.1.expires_at <= b.1.expires_at => Some(b),
            _ => Some(cand),
        })
        .ok_or_else(|| {
            anyhow::anyhow!(
                "no OIDC auth entry found in {}. Run `grok login` first.",
                path.display()
            )

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Check permissions: `ls -l $([ -n "$GROK_HOME" ] && echo $GROK_HOME || echo ~/.grok)/auth.json` and ensure the running user can read it (chmod 600, chown).
  2. Verify GROK_HOME points to the directory where `grok login` actually wrote auth.json.
  3. Re-run `grok login` to recreate the file.
  4. Ensure the path is a regular file, not a directory or broken symlink.

Example fix

# before: unreadable file
-rw------- root root auth.json   # app runs as 'appuser'
# after
sudo chown appuser:appauth auth.json && chmod 600 auth.json
Defensive patterns

Strategy: validation

Validate before calling

let path = default_auth_path()?;
let meta = std::fs::metadata(&path).map_err(|e| anyhow::anyhow!("auth file {} not stat-able: {e}", path.display()))?;
if !meta.is_file() { anyhow::bail!("{} is not a regular file", path.display()); }
let f = std::fs::File::open(&path).map_err(|e| anyhow::anyhow!("{} unreadable: {e} — check permissions/user", path.display()))?;

Try / catch

match read_auth_entry().await {
    Ok(entry) => entry,
    Err(e) if e.to_string().starts_with("failed to read") => {
        eprintln!("auth.json unreadable: check permissions and the user running the process");
        prompt_relogin();
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling read_auth_entry (or `provider()`) when auth.json exists but is unreadable: wrong permissions (e.g. owned by another user), it is a directory, an I/O error occurs, or the path resolved from GROK_HOME/HOME points somewhere unexpected.

Common situations: auth.json permissions changed by another tool or sync software; running the app as a different user than the one that ran `grok login`; GROK_HOME pointing at a stale/moved location; NFS/permission issues on shared hosts.

Related errors


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