{"record":{"id":"75f502ecaa27ad04","repo":"atuinsh/atuin","slug":"hub-password-change-failed-with-status-status","errorCode":null,"errorMessage":"Hub password change failed with status {status}","messagePattern":"Hub password change failed with status (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-client/src/auth.rs","lineNumber":420,"sourceCode":"                Some(\"2fa_required\") => return Ok(MutateResponse::TwoFactorRequired),\n                Some(\"invalid_2fa_code\") => {\n                    bail!(\"invalid two-factor code\");\n                }\n                _ => {\n                    bail!(\"{}\", err.reason);\n                }\n            }\n        }\n\n        match status {\n            StatusCode::UNAUTHORIZED => {\n                bail!(\"current password is incorrect\");\n            }\n            StatusCode::FORBIDDEN => {\n                bail!(\"invalid login details\");\n            }\n            _ => {\n                bail!(\"Hub password change failed with status {status}\");\n            }\n        }\n    }\n\n    async fn delete_account(\n        &self,\n        password: &str,\n        totp_code: Option<&str>,\n    ) -> Result<MutateResponse> {\n        let hub_token = self.hub_token.as_deref().ok_or_else(|| {\n            eyre::eyre!(\"Not logged in to Atuin Hub. Please run 'atuin login' to authenticate.\")\n        })?;\n\n        if !hub_token.starts_with(\"atapi_\") {\n            bail!(\n                \"Your Hub session token is invalid. Please run 'atuin login' to re-authenticate \\\n                 with Atuin Hub.\"\n            );","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/atuinsh/atuin/blob/900007c48045867e7f44b0f9bc55ad9dbe99ee0d/crates/atuin-client/src/auth.rs#L402-L438","documentation":"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.","triggerScenarios":"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`.","commonSituations":"Hub outage or maintenance window; reverse proxy returning HTML 502 pages; rate limiting from rapid retries; client/server version skew producing unexpected payloads.","solutions":["Check the status code: retry with backoff for 429/5xx.","Check Atuin Hub status for outages.","Update Atuin to keep client/server error schemas aligned.","Inspect any proxy between client and Hub that could rewrite responses."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Probe server health before the mutation\nlet healthy = reqwest::get(format!(\"{hub}/health\"))\n    .await.map(|r| r.status().is_success()).unwrap_or(false);","typeGuard":null,"tryCatchPattern":"match client.change_password(cur, new, totp).await {\n    Err(e) if e.to_string().contains(\"failed with status\") => {\n        // 429/5xx with unparseable body: retry with exponential backoff\n    }\n    other => { /* handle */ }\n}","preventionTips":["Retry with backoff on 429/5xx; never tight-loop the endpoint.","Check Hub status pages during outages.","Keep client version in sync with server.","Audit intermediaries (proxies/LBs) that can replace JSON error bodies."],"tags":["http","api","network"],"backgroundTag":"unexpected-http-status","analyzedSha":"900007c48045867e7f44b0f9bc55ad9dbe99ee0d","analyzedAt":"2026-09-19T12:52:51.491Z","contentChangedAt":"2026-09-19T12:52:51.491Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}