atuinsh/atuin · error

Hub password change failed with status

Error message

Hub password change failed with status {status}

What it means

Catch-all in `change_password` (crates/atuin-client/src/auth.rs:420): the Hub returned a non-success status that is neither 401 nor 403, and the body was not a parseable `HubErrorResponse`. Only the HTTP status is reported.

Solutions

  1. Check the status code: retry with backoff for 429/5xx.
  2. Check Atuin Hub status for outages.
  3. Update Atuin to keep client/server error schemas aligned.
  4. Inspect any proxy between client and Hub that could rewrite responses.
Defensive patterns

Strategy: retry

Validate before calling

// Probe server health before the mutation
let healthy = reqwest::get(format!("{hub}/health"))
    .await.map(|r| r.status().is_success()).unwrap_or(false);

Try / catch

match client.change_password(cur, new, totp).await {
    Err(e) if e.to_string().contains("failed with status") => {
        // 429/5xx with unparseable body: retry with exponential backoff
    }
    other => { /* handle */ }
}

Prevention

When it happens

Trigger: PATCH to `/api/v0/account/password` returns e.g. 429 (rate limited), 500/502/503 (server error), or 413, with a body that fails JSON deserialization into `HubErrorResponse`.

Common situations: Hub outage or maintenance window; reverse proxy returning HTML 502 pages; rate limiting from rapid retries; client/server version skew producing unexpected payloads.

Related errors


AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19). Data as JSON: /api/errors/75f502ecaa27ad04. Report an issue: GitHub.

Appendix: source

Thrown at crates/atuin-client/src/auth.rs:420

                Some("2fa_required") => return Ok(MutateResponse::TwoFactorRequired),
                Some("invalid_2fa_code") => {
                    bail!("invalid two-factor code");
                }
                _ => {
                    bail!("{}", err.reason);
                }
            }
        }

        match status {
            StatusCode::UNAUTHORIZED => {
                bail!("current password is incorrect");
            }
            StatusCode::FORBIDDEN => {
                bail!("invalid login details");
            }
            _ => {
                bail!("Hub password change failed with status {status}");
            }
        }
    }

    async fn delete_account(
        &self,
        password: &str,
        totp_code: Option<&str>,
    ) -> Result<MutateResponse> {
        let hub_token = self.hub_token.as_deref().ok_or_else(|| {
            eyre::eyre!("Not logged in to Atuin Hub. Please run 'atuin login' to authenticate.")
        })?;

        if !hub_token.starts_with("atapi_") {
            bail!(
                "Your Hub session token is invalid. Please run 'atuin login' to re-authenticate \
                 with Atuin Hub."
            );

View on GitHub (pinned to 900007c480)