atuinsh/atuin · error
Could not login due to version mismatch
Error message
Could not login due to version mismatch
What it means
Like registration, `login` verifies the server version header after posting credentials. If `ensure_version` fails (server too old or version negotiation fails), login is refused with this message because the old server cannot produce a compatible session.
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 c0c717ab04)
Solutions
- Upgrade the sync server to at least the client's major version
- Ensure reverse proxies do not strip the `x-atuin-version` header
- Pin/downgrade the client temporarily if the server cannot be upgraded
Example fix
// before atuin login -u alice # server v17, client v18 // after # upgrade server to v18 first, then: atuin login -u alice
Defensive patterns
Strategy: validation
Validate before calling
// preflight login version check
let resp = client.get(format!("{address}/health")).send().await?;
let v = resp.headers().get("x-atuin-version").and_then(|v| v.to_str().ok());
let ok = v.map(|v| Version::parse(v).map(|sv| sv.major >= ATUIN_VERSION.major).unwrap_or(false));
if ok != Some(true) { eprintln!("server too old for this client"); return Ok(()); } Try / catch
match login(...).await {
Err(e) if e.to_string().contains("version mismatch") => {
eprintln!("upgrade the sync server (or downgrade the client) and retry");
}
other => other?,
} Prevention
- Track server releases alongside client releases
- Test login against staging after server upgrades
- Ensure proxies forward x-atuin-version
When it happens
Trigger: `atuin login` against a sync server whose reported version is older than the client's major version, so `ensure_version` returns false
Common situations: Self-hosted server lagging behind a breaking client release; corporate proxy or cached old server image
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- could not register user due to version mismatch
- Server not reporting its version: it is either too old or un
- invalid id UUID format in sqlite DB
- {message}
- {message}. Enable `daemon.autostart = true` or restart the d
AI-assisted analysis of atuinsh/atuin@c0c717ab04 (2026-09-12).
Data as JSON: /api/errors/eaca4794094cbcaf.
Report an issue: GitHub.