atuinsh/atuin · error
Could not login due to version mismatch
Error message
Could not login due to version mismatch
What it means
After a login POST, `ensure_version` verifies the server version from the response headers. Login is aborted when the server is too old (or too new) for the client to interoperate with, preventing a partially working session.
Solutions
- Upgrade the sync server to at least the client's major/minor version
- Or downgrade the client to match the server
- Verify the server reports a version header at all (curl the login endpoint)
- Keep client and server updated together
Defensive patterns
Strategy: validation
Validate before calling
let server_ver = fetch_server_version(&address).await?;
if semver::Version::parse(&server_ver)?.major < ATUIN_VERSION.major {
eprintln!("server too old for this client; upgrade server first");
return Ok(());
} Try / catch
match login(&client, &address, req).await {
Err(e) if e.to_string().contains("version mismatch") => {
// guide user to upgrade server or downgrade client
Err(e)
}
other => other,
} Prevention
- Upgrade server before upgrading clients
- Test login after any server upgrade
- Avoid mixing nightly clients with stable servers
When it happens
Trigger: Running `atuin login` against a sync server whose version header fails the client's compatibility check.
Common situations: Self-hosted Atuin server lagging behind a recently updated client; enterprise deployments pinned to old releases.
Related errors
- could not register user due to version mismatch
- {}
- failed to parse server version
- Hub login failed with status
- invalid credentials
AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19).
Data as JSON: /api/errors/eaca4794094cbcaf.
Report an issue: GitHub.
Appendix: source
Thrown at crates/atuin-client/src/api_client.rs:177
}
#[instrument(level = "trace", skip_all, err)]
pub async fn login(
address: &Url,
req: LoginRequest,
extra_headers: &HashMap<String, String>,
) -> Result<LoginResponse> {
let url = address.append(["login"])?;
let client = client_builder(extra_headers).build()?;
let mut headers = extra_headers_map(extra_headers)?;
headers.insert(USER_AGENT, APP_USER_AGENT.parse()?);
let resp = client.post(url).headers(headers).json(&req).send().await?;
let resp = handle_resp_error(resp).await?;
if !ensure_version(&resp)? {
bail!("Could not login due to version mismatch");
}
let session = resp.json::<LoginResponse>().await?;
Ok(session)
}
#[cfg(feature = "check-update")]
#[instrument(level = "trace", skip_all, err)]
pub async fn latest_version() -> Result<Version> {
use atuin_domain::api::IndexResponse;
let url = crate::settings::DEFAULT_SYNC_URL.clone();
let client = reqwest::Client::new();
let resp = client.get(url).header(USER_AGENT, APP_USER_AGENT).send().await?;
let resp = handle_resp_error(resp).await?;
let index = resp.json::<IndexResponse>().await?;View on GitHub (pinned to 900007c480)