atuinsh/atuin · error

unknown HistoryRecord type {n}

Error message

unknown HistoryRecord type {n}

What it means

Decoder guard in HistoryRecord::deserialize: the record store decoded a history record whose leading tag byte is neither 0 (Create) nor 1 (Delete). This indicates data corruption, a truncated/garbled encrypted payload, or a record written by a newer/older Atuin version using an undocumented type byte — the wire format has diverged from what this client understands.

Source

Thrown at crates/atuin-client/src/history/store.rs:121

                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();

/// How many records `incremental_build` decodes concurrently. Decoding is read-then-decrypt per
/// record; overlapping the reads keeps the record store's pool busy without unbounded fan-out.
/// Kept under the store's connection pool size so decodes don't starve other readers.
const DECODE_CONCURRENCY: usize = 4;

impl HistoryStore {
    #[must_use]
    pub fn new(store: SqliteStore, host_id: HostId, encryption_key: paseto_v4::Key) -> Self {
        Self {

View on GitHub (pinned to c0c717ab04)

Solutions

  1. Upgrade atuin on all machines to the newest version
  2. Re-sync the local record store from the Hub if data is damaged
  3. Pin identical atuin versions across devices that share sync
Defensive patterns

Strategy: try-catch

Type guard

fn is_supported_tag(tag: u64) -> bool {
    matches!(tag, 0 | 1) // known HistoryRecord variants
}

Try / catch

match HistoryRecord::deserialize(bytes) {
    Ok(rec) => apply(rec),
    Err(e) if e.to_string().contains("unknown HistoryRecord type") => {
        log::warn!("record from newer client version; upgrade atuin");
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Deserializing a record written by a newer atuin version that introduced new HistoryRecord variants, or reading corrupted bytes where the tag field is garbage.

Common situations: Mixed atuin versions across synced machines; record store corrupted by partial writes.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of atuinsh/atuin@c0c717ab04 (2026-09-12). Data as JSON: /api/errors/5286c47105b6c596. Report an issue: GitHub.