atuinsh/atuin · error
unknown kv record version
Error message
unknown kv record version {other:?} What it means
The KV record decoder reads a leading version byte and implements only known versions. Any other version triggers 'unknown kv record version'. This protects against decoding payloads whose binary format changed between releases.
Solutions
- Upgrade atuin-kv / atuin to a version supporting the record's version byte
- Skip unknown-version records instead of failing the entire sync
- Re-create the KV data with the current client
Defensive patterns
Strategy: try-catch
Validate before calling
// Check the KV record version byte before decoding
// fn is_supported_kv_version(payload: &[u8]) -> bool {
// payload.first() == Some(&KV_KNOWN_VERSION)
// } Type guard
fn is_supported_kv_version(payload: &[u8]) -> bool {
payload.first() == Some(&KV_KNOWN_VERSION)
} Try / catch
match KvRecord::deserialize(&mut bytes) {
Ok(rec) => apply(rec),
Err(e) if e.to_string().contains("unknown kv record version") => {
log::warn!("kv record from newer atuin; skipping until upgrade");
}
Err(e) => return Err(e),
} Prevention
- Upgrade atuin before consuming records written by newer clients
- Keep all synced hosts on compatible versions
- Back up and re-create KV data across major format changes
When it happens
Trigger: Deserializing a KV record whose version byte is not one compiled into this build — commonly newer-format records synced down to an older client.
Common situations: Version skew between synced machines; restoring old records into a newer store or vice versa.
Related errors
- trailing bytes in encoded kvrecord. malformed
- unknown alias record version
- unknown AliasRecord type
- unknown Dotfiles var record type
- unknown script record version
AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19).
Data as JSON: /api/errors/c4fa552d44a1e4bb.
Report an issue: GitHub.
Appendix: source
Thrown at crates/atuin-kv/src/store/record.rs:97
let (value, bytes) =
decode::read_str_from_slice(bytes).map_err(error_report)?;
(Some(value.to_owned()), bytes)
} else {
(None, bytes)
};
if !bytes.is_empty() {
bail!("trailing bytes in encoded kvrecord. malformed");
}
Ok(Self {
namespace: namespace.to_owned(),
key: key.to_owned(),
value,
})
}
other => {
bail!("unknown kv record version {other:?}");
}
}
}
}
#[cfg(test)]
mod tests {
use atuin_domain::record::RecordVersion;
use rstest::rstest;
use super::{DecryptedData, KvRecord};
#[rstest]
#[case::some(
Some("baz".to_owned()),
&[0x94, 0xa3, b'f', b'o', b'o', 0xa3, b'b', b'a', b'r', 0xc3, 0xa3, b'b', b'a', b'z']
)]
#[case::none(None, &[0x94, 0xa3, b'f', b'o', b'o', 0xa3, b'b', b'a', b'r', 0xc2])]View on GitHub (pinned to 900007c480)