atuinsh/atuin · error · SyncError
WrongKey
Error message
WrongKey
What it means
`SyncError::WrongKey` is returned by `check_key_against_index` when a record fetched from the sync server cannot be decrypted with the local encryption key (`record.decrypt(key)` errs). It means the key being used does not match the key the records were encrypted with — typically during `atuin login`/`sync` key verification.
Solutions
- Log in again supplying the correct original encryption key (from the machine that first ran `atuin register`, stored in ~/.local/share/atuin/key).
- Export the key from a working machine with `atuin key` and use it at login (`atuin login --key <key>`).
- If the key is truly lost, register a fresh account (accepting history loss) so all records re-encrypt under the new key.
Example fix
// before atuin login --username me --password pw --key <wrong-key> // after atuin key # on the original machine atuin login --username me --password pw --key <correct-key-from-atuin-key>
Defensive patterns
Strategy: try-catch
Validate before calling
// verify the local key decrypts an existing local record before syncing let local_key = atuin_client::encryption::load_key()?; // run `atuin key` on the original machine and compare before logging in
Try / catch
match sync::check_encryption_key().await {
Some(SyncError::WrongKey) => eprintln!("Encryption key mismatch: re-login with the original key from `atuin key` on the registering machine"),
Some(other) => eprintln!("sync check failed: {other:?}"),
None => { /* key OK, proceed with sync */ }
} Prevention
- Back up ~/.local/share/atuin/key; it is the only way to decrypt synced history.
- Run `atuin key` on a working machine before logging in on a new one.
- Never regenerate the key file; copy it between machines instead.
- Register one account per key; don't reuse keys across accounts.
When it happens
Trigger: During `check_encryption_key`, a remote record is downloaded and `record.decrypt(key)` fails (crates/atuin-client/src/record/sync/mod.rs:223), producing `SyncError::WrongKey`. Triggered by logging in with an encryption key that differs from the one the account's records were encrypted with.
Common situations: Re-creating an account and reusing an old key; copying a key from a different atuin account; key file at ~/.local/share/atuin/key being regenerated or from another machine; typos when pasting the key during login.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- the encryption key on this machine does not match the data…
- could not sync records due to version mismatch
- invalid id UUID format in sqlite DB
- key file vanished immediately after a concurrent write
- No encryption key provided
AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19).
Data as JSON: /api/errors/485878d4c0602ab7.
Report an issue: GitHub.
Appendix: source
Thrown at crates/atuin-client/src/record/sync/mod.rs:223
let sample = remote_index
.hosts
.iter()
.flat_map(|(host, tags)| {
tags.keys().map(move |tag| RecordSeriesKey::new(*host, tag.clone()))
})
// Plaintext series (packfile manifests) would fail decryption with any key, so they
// can't be used to check whether the local key matches the remote.
.find(|series| !series.tag.is_plaintext());
let series = sample?;
let record = match self.client.records(&series).one().await {
Ok(Some(record)) => record,
Ok(None) => return None,
Err(e) => return Some(SyncError::RemoteRequestError { msg: e.to_string() }),
};
record.decrypt(key).err().map(|_| SyncError::WrongKey)
}
/// Fetch the remote's record status index.
#[instrument(level = "trace", skip_all, err)]
pub async fn record_status(&self) -> Result<RecordStatus, SyncError> {
self.client
.record_status()
.await
.map_err(|e| SyncError::RemoteRequestError { msg: e.to_string() })
}
#[instrument(level = "trace", skip_all, err)]
pub async fn diff(&self) -> Result<(Vec<Diff>, RecordStatus), SyncError> {
let local_index = self
.store
.status()
.await
.map_err(|e| SyncError::LocalStoreError { msg: e.to_string() })?;View on GitHub (pinned to 900007c480)