atuinsh/atuin · error
trailing bytes decoding HistoryRecord::Delete - malformed? g
Error message
trailing bytes decoding HistoryRecord::Delete - malformed? got {bytes:?} What it means
While decoding a HistoryRecord tagged as Delete (tag 1), the payload contained bytes left over after reading the record ID. The record store treats this as corruption since Delete records must contain exactly one string field.
Source
Thrown at crates/atuin-client/src/history/store.rs:112
// 0 -> HistoryRecord::Create
0 => {
// not super useful to us atm, but perhaps in the future
// written by write_bin above
let _ = decode::read_bin_len(&mut bytes).map_err(error_report)?;
let record =
History::deserialize(bytes.remaining_slice(), version).map_err(error_report)?;
Ok(Self::Create(record))
}
// 1 -> HistoryRecord::Delete
1 => {
let bytes = bytes.remaining_slice();
let (id, bytes) = decode::read_str_from_slice(bytes).map_err(error_report)?;
if !bytes.is_empty() {
bail!(
"trailing bytes decoding HistoryRecord::Delete - malformed? got {bytes:?}"
);
}
Ok(Self::Delete(id.parse()?))
}
n => {
bail!("unknown HistoryRecord type {n}");
}
}
}
}
/// How many entries `incremental_build` holds in memory, and the most it puts into a single
/// `save_bulk`/`delete_rows` transaction.
const BUILD_BATCH_SIZE: NonZeroUsize = NonZeroUsize::new(5000).unwrap();
View on GitHub (pinned to c0c717ab04)
Solutions
- Verify the record store integrity; re-sync from the Hub by deleting the local record DB and re-downloading
- Update atuin to the latest version on all machines to align record formats
- Restore the record store from backup if corruption persists
Defensive patterns
Strategy: try-catch
Type guard
fn is_wellformed_delete(payload: &[u8]) -> bool {
match decode::read_str_from_slice(payload) {
Ok((_, rest)) => rest.is_empty(),
Err(_) => false,
}
} Try / catch
match HistoryRecord::deserialize(bytes) {
Ok(rec) => apply(rec),
Err(e) if e.to_string().contains("trailing bytes") => {
log::warn!("corrupt record skipped: {e}");
// skip or trigger re-sync
}
Err(e) => return Err(e),
} Prevention
- Run identical atuin versions on all synced machines
- Shut down cleanly; avoid killing the process mid-write to the record store
- Keep backups of the local record DB
When it happens
Trigger: Deserializing a binary record whose Delete payload has extra trailing bytes — truncated/corrupted record store files, or records written by an incompatible format version.
Common situations: Partially written or damaged SQLite record blobs; syncing records from a newer/older atuin version with format drift.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- unknown HistoryRecord type {n}
- trailing bytes in encoded shell alias record. malformed
- invalid id UUID format in sqlite DB
- invalid host UUID format in sqlite DB
- failed to parse uuid for local store status
AI-assisted analysis of atuinsh/atuin@c0c717ab04 (2026-09-12).
Data as JSON: /api/errors/1813dfdca0291792.
Report an issue: GitHub.