{"record":{"id":"66787f59b12aa306","repo":"atuinsh/atuin","slug":"hub-login-failed-with-status-status","errorCode":null,"errorMessage":"Hub login failed with status {status}","messagePattern":"Hub login failed with status (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-client/src/auth.rs","lineNumber":319,"sourceCode":"                session: login.session,\n                auth_type: login.auth,\n            });\n        }\n\n        if status == StatusCode::FORBIDDEN\n            && let Ok(err) = resp.json::<HubErrorResponse>().await\n        {\n            if err.code.as_deref() == Some(\"2fa_required\") {\n                return Ok(AuthResponse::TwoFactorRequired);\n            }\n            bail!(\"{}\", err.reason);\n        }\n\n        if status == StatusCode::UNAUTHORIZED {\n            bail!(\"invalid credentials\");\n        }\n\n        bail!(\"Hub login failed with status {status}\");\n    }\n\n    async fn register(&self, username: &str, email: &str, password: &str) -> Result<AuthResponse> {\n        let url = self.address.append_path(\"api/v0/register\")?;\n        let client = reqwest::Client::new();\n\n        let resp = client\n            .post(url)\n            .header(USER_AGENT, APP_USER_AGENT)\n            .header(ATUIN_HEADER_VERSION, ATUIN_CARGO_VERSION)\n            .json(&serde_json::json!({\n                \"email\": email,\n                \"username\": username,\n                \"password\": password,\n            }))\n            .send()\n            .await\n            .context(\"failed to connect to Atuin Hub\")?;","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/atuinsh/atuin/blob/900007c48045867e7f44b0f9bc55ad9dbe99ee0d/crates/atuin-client/src/auth.rs#L301-L337","documentation":"Final fallback in `HubAuthClient::login`: any non-success status that is not 403-with-parseable-body and not 401 becomes this bail embedding the HTTP status. It covers 3xx redirections, 404, 429, and all 5xx responses from the Hub or intermediaries.","triggerScenarios":"POST `api/v0/login` returns e.g. 404 (wrong base URL/path), 429 (rate limited), 500/502/503 (Hub or proxy outage), or an unexpected redirect.","commonSituations":"Misconfigured Hub address (wrong host/path producing 404); Hub service disruption (5xx); aggressive rate limiting after repeated failed logins; corporate proxy or captive portal intercepting the request.","solutions":["Check status embedded in the message: 4xx means fix the request/URL, 5xx means server-side","Verify the configured Hub address is correct and reachable (`curl https://api.atuin.sh/api/v0/login`)","Wait and retry with backoff if the status was 429 or 5xx (check https://status for Hub incidents)","Bypass proxies/VPN to rule out intermediary interference","Update the Atuin CLI in case the login API path changed"],"exampleFix":"// before: opaque status-only bail\nbail!(\"Hub login failed with status {status}\");\n// after: surface response body for diagnosis\nlet body = resp.text().await.unwrap_or_default();\nbail!(\"Hub login failed with status {status}: {body}\");","handlingStrategy":"retry","validationCode":"// Check Hub reachability before login\nlet status = reqwest::get(\"https://api.atuin.sh/health\").await?.status();\nif !status.is_success() {\n    bail!(\"Hub unreachable/unhealthy: {status}\");\n}","typeGuard":"fn is_unmapped_login_status(err: &Report) -> Option<u16> {\n    let msg = err.to_string();\n    msg.strip_prefix(\"Hub login failed with status \")\n        .and_then(|s| s.split(' ').next())\n        .and_then(|code| code.parse().ok())\n}","tryCatchPattern":"match hub.login(username, password, totp).await {\n    Err(e) if e.to_string().starts_with(\"Hub login failed with status\") => {\n        let retryable = e.to_string().contains(\"429\")\n            || e.to_string().contains(\"5\"); // 5xx\n        if retryable {\n            tokio::time::sleep(Duration::from_secs(10)).await;\n            // retry with backoff\n        } else {\n            eprintln!(\"fix Hub address/request: {e}\");\n        }\n    }\n    other => { /* handle normally */ }\n}","preventionTips":["Validate the configured Hub address resolves to the real API host","Retry 429/5xx with exponential backoff rather than immediate repeats","Watch Hub status/announcements during outages","Exclude corporate proxies/VPNs when diagnosing unexpected login statuses"],"tags":["http","atuin-hub","login","network"],"backgroundTag":"http-error-response","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"}