xai-org/grok-build · error · OidcError

OidcError::SaveAuth

Error message

OidcError::SaveAuth

What it means

After a successful OIDC token exchange, `run_login_flow_with_config` persists the built GrokAuth via `auth_manager.update(auth)`. This error wraps any failure of that persistence step (writing credentials to storage), so the login technically succeeded against the IDP but the credentials could not be saved.

Source

Thrown at crates/codegen/xai-grok-shell/src/auth/oidc/login.rs:539

    let user_info = extract_user_info(
        tokens.id_token.as_deref(),
        &discovery,
        &oidc.issuer,
        &oidc.client_id,
        &nonce,
        resolved_principal_type.as_deref(),
        resolved_principal_id.as_deref(),
        resolved_team_id,
    )
    .await?;
    tracing::debug!(user_id = %user_info.user_id, "OIDC: extracted user info");

    let mut auth = build_grok_auth(tokens, user_info, &oidc.issuer, &oidc.client_id);
    auth_manager.enrich_auth_inline(&mut auth).await;
    let auth = auth_manager
        .update(auth)
        .await
        .map_err(|e| anyhow::Error::new(OidcError::SaveAuth(e.to_string())))?;
    tracing::info!(user_id = %auth.user_id, "OIDC: login complete, credentials saved");

    Ok((auth, true))
}

/// Successful OIDC callback payload.
#[derive(Debug, PartialEq, Eq)]
struct Callback {
    code: String,
    state: String,
}

/// Result from the OIDC callback: either a [`Callback`] or an IdP error message.
type CallbackResult = Result<Callback, String>;

#[cfg(test)]
mod tests {
    use super::super::test_helpers::*;

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Check write permissions and free space on the credentials storage location (~/.config or the tool's auth dir).
  2. Remove a corrupted credentials file and re-run login.
  3. Ensure no other process holds a lock on the auth store; close concurrent sessions and retry.
  4. In containers/CI, set HOME/XDG_CONFIG_HOME to a writable path and mount a volume for the credentials.
  5. Inspect the wrapped error string (in OidcError::SaveAuth) for the exact IO/serialization cause.

Example fix

// before: read-only home in container
$ docker run --read-only grok login  # SaveAuth fails
// after
$ docker run -v grok-config:/root/.config grok login  # writable volume, save succeeds
Defensive patterns

Strategy: validation

Validate before calling

// preflight: verify the credentials directory is writable before login
let auth_dir = dirs::home_dir().unwrap().join(".config/grok");
std::fs::create_dir_all(&auth_dir)?;
let probe = auth_dir.join(".write_probe");
std::fs::write(&probe, b"ok")?;
std::fs::remove_file(&probe)?;

Type guard

fn is_save_auth(err: &anyhow::Error) -> bool {
    err.downcast_ref::<OidcError>()
        .map_or(false, |e| matches!(e, OidcError::SaveAuth(_)))
}

Try / catch

if is_save_auth(&err) {
    eprintln!("Login succeeded but saving credentials failed. Check permissions/free space on the auth store, then retry.");
}

Prevention

When it happens

Trigger: auth_manager.update(auth).await returns Err in run_login_flow_with_config after build_grok_auth/enrich_auth_inline succeed — wrapped as OidcError::SaveAuth(e.to_string()).

Common situations: Credentials file/directory not writable (permissions, read-only FS, full disk); storage locked by a concurrent session; corrupted existing credentials file failing to serialize; HOME/XDG path misconfigured in CI containers; disk quota exceeded.

Related errors


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