{"record":{"id":"3318a2690f573133","repo":"xai-org/grok-build","slug":"failed-to-read-e-3318a2","errorCode":null,"errorMessage":"failed to read {}: {e}","messagePattern":"failed to read (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-workspace/src/hub_auth/mod.rs","lineNumber":108,"sourceCode":"}\n\n/// Read the active OIDC entry and its scope key. The key is threaded to the\n/// refresh write so rotation updates exactly the entry that was read.\n///\n/// When several OIDC entries qualify, pick the **latest `expires_at`** — the\n/// entry the shell is actively refreshing. The previous first-key selection\n/// was alphabetical and could rotate a *different principal's* RT chain than\n/// the one the user's sessions use.\nfn read_auth_entry(path: &Path) -> anyhow::Result<(String, AuthEntry)> {\n    if !path.exists() {\n        anyhow::bail!(\n            \"No auth credentials found at {}. Run `grok login` first.\",\n            path.display()\n        );\n    }\n\n    let content = std::fs::read_to_string(path)\n        .map_err(|e| anyhow::anyhow!(\"failed to read {}: {e}\", path.display()))?;\n    let entries: BTreeMap<String, AuthEntry> = serde_json::from_str(&content)\n        .map_err(|e| anyhow::anyhow!(\"failed to parse {}: {e}\", path.display()))?;\n\n    entries\n        .into_iter()\n        .filter(|(_, e)| e.refresh_token.is_some() && e.oidc_issuer.is_some())\n        // Strictly-greater comparison: ties (including all-`None`) keep the\n        // first candidate in BTreeMap (alphabetical) order, so single-entry\n        // and legacy no-`expires_at` files behave exactly as before.\n        .fold(None::<(String, AuthEntry)>, |best, cand| match best {\n            Some(b) if cand.1.expires_at <= b.1.expires_at => Some(b),\n            _ => Some(cand),\n        })\n        .ok_or_else(|| {\n            anyhow::anyhow!(\n                \"no OIDC auth entry found in {}. Run `grok login` first.\",\n                path.display()\n            )","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-workspace/src/hub_auth/mod.rs#L90-L126","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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).","Verify GROK_HOME points to the directory where `grok login` actually wrote auth.json.","Re-run `grok login` to recreate the file.","Ensure the path is a regular file, not a directory or broken symlink."],"exampleFix":"# before: unreadable file\n-rw------- root root auth.json   # app runs as 'appuser'\n# after\nsudo chown appuser:appauth auth.json && chmod 600 auth.json","handlingStrategy":"validation","validationCode":"let path = default_auth_path()?;\nlet meta = std::fs::metadata(&path).map_err(|e| anyhow::anyhow!(\"auth file {} not stat-able: {e}\", path.display()))?;\nif !meta.is_file() { anyhow::bail!(\"{} is not a regular file\", path.display()); }\nlet f = std::fs::File::open(&path).map_err(|e| anyhow::anyhow!(\"{} unreadable: {e} — check permissions/user\", path.display()))?;","typeGuard":null,"tryCatchPattern":"match read_auth_entry().await {\n    Ok(entry) => entry,\n    Err(e) if e.to_string().starts_with(\"failed to read\") => {\n        eprintln!(\"auth.json unreadable: check permissions and the user running the process\");\n        prompt_relogin();\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Run `grok login` as the same user that runs the application","Keep auth.json chmod 600 and owned by the service user","Do not point GROK_HOME at synced/moved directories","Verify file access in a startup readiness check"],"tags":["auth","filesystem","permissions","io"],"backgroundTag":"file-read-failed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}