atuinsh/atuin · error
usage request failed
Error message
usage request failed ({status}) What it means
Fires in fetch_usage when the hub's GET api/cli/usage endpoint responds with a non-success HTTP status. This is not a network failure — the request reached the server, which rejected it (e.g. 401/403 for an expired or invalid bearer token, 429 rate limiting, or 5xx hub-side trouble). The status code is interpolated into the message so callers can distinguish auth problems (fix by re-authenticating) from transient server errors (fix by retrying later). It surfaces when a user refreshes their credit/usage snapshot outside of a chat session, mirroring the credits object normally delivered on the chat done event.
Solutions
- Re-authenticate if the status is 401/403
- Wait and retry if the status is 429 (rate limit) or 5xx
- Check connectivity and any proxy settings
- Update Atuin if the endpoint has changed
Defensive patterns
Strategy: retry
Try / catch
match fetch_usage(&client, &token).await {
Ok(snapshot) => snapshot,
Err(e) if e.to_string().contains("429") => { tokio::time::sleep(backoff).await; retry().await? }
Err(e) if e.to_string().contains("401") => { reauth().await?; retry().await? }
Err(e) => return Err(e),
} Prevention
- Re-authenticate on 401 before retrying
- Back off on 429 instead of hammering the endpoint
- Cache usage snapshots to reduce request volume
When it happens
Trigger: Calling `fetch_usage` when the backend returns 4xx/5xx — invalid/expired auth token, rate limiting, or service error.
Common situations: Checking AI usage with a stale session (401), exceeding plan limits (429), or temporary backend outage (5xx).
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- model list request failed
- Hub account deletion failed with status
- Hub password change failed with status
- Hub registration failed with status
- Hub login failed with status
AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19).
Data as JSON: /api/errors/7ba02491697e31c2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/atuin-ai/src/usage.rs:106
}
/// Fetch current usage from the hub. Mirrors the `credits` object on the
/// chat `done` event, for refreshing without starting a chat.
pub async fn fetch_usage(endpoint: &reqwest::Url, token: &str) -> Result<UsageSnapshot> {
let url = endpoint.append_path("api/cli/usage")?;
let response = reqwest::Client::new()
.get(url)
.header(USER_AGENT, crate::stream::APP_USER_AGENT)
.bearer_auth(token)
.timeout(Duration::from_secs(10))
.send()
.await
.context("failed to fetch usage")?;
let status = response.status();
if !status.is_success() {
eyre::bail!("usage request failed ({status})");
}
response.json::<UsageSnapshot>().await.context("failed to parse usage response")
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
#[test]
fn deserializes_server_payload() {
// Shape documented in the hub's CliUsageController / credits_payload.
let json = r#"{
"period": "calendar_monthly",
"resets_at": "2026-08-01T00:00:00Z",
"requests": {"used": 3, "limit": -1},View on GitHub (pinned to 900007c480)