atuinsh/atuin · error

too many entries in v0 script record

Error message

too many entries in v0 script record

What it means

A v0 script record must be a MsgPack array of exactly 6 entries (id, name, description, and the remaining script fields). The script record deserializer checks the array length before reading and rejects other counts. Note this deserializer uses unwrap() on subsequent reads, so this ensure! is the structured guard against shape mismatches.

Solutions

  1. Re-create the script with the current CLI so it is encoded with the expected 6-field schema.
  2. Fix the writer to emit exactly six fields in the documented order for v0 script records.
  3. Sync-align Atuin versions across machines.

Example fix

// before: encode::to_bytes(&(id, name, description))
// after:  encode::to_bytes(&(id, name, description, script, tags, created))
Defensive patterns

Strategy: validation

Validate before calling

let value: rmpv::Value = rmpv::decode::read_value(&mut cursor)?;
// v0 script record requires exactly 6 fields
assert_eq!(value.as_array().map(|a| a.len()), Some(6));

Type guard

fn is_well_formed_v0_script(payload: &[u8]) -> bool {
    rmpv::decode::read_value(&mut std::io::Cursor::new(payload))
        .ok()
        .and_then(|v| v.as_array().map(|a| a.len() == 6))
        .unwrap_or(false)
}

Try / catch

match Script::deserialize(&bytes) {
    Ok(script) => install(script),
    Err(e) if e.to_string().contains("too many entries") => {
        log::warn("malformed script record dropped: {e}");
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Deserializing a v0 script record whose array length != 6 — e.g. records written by a different script schema version, encoders adding/removing fields, or corrupted payloads.

Common situations: Script records synced across Atuin versions with differing script schemas, manual record construction, or data corruption in the record store.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of atuinsh/atuin@900007c480 (2026-09-19). Data as JSON: /api/errors/483b09c3094fea8e. Report an issue: GitHub.

Appendix: source

Thrown at crates/atuin-scripts/src/store/script.rs:69

        encode::write_str(&mut output, &self.name)?;
        encode::write_str(&mut output, &self.description)?;
        encode::write_str(&mut output, &self.shebang)?;
        encode::write_array_len(&mut output, u32::conv(self.tags.len()))?;

        for tag in &tags {
            encode::write_str(&mut output, tag)?;
        }

        encode::write_str(&mut output, &self.script)?;

        Ok(DecryptedData(output))
    }

    pub fn deserialize(bytes: &[u8]) -> Result<Self> {
        let mut bytes = decode::Bytes::new(bytes);
        let nfields = decode::read_array_len(&mut bytes).unwrap();

        ensure!(nfields == 6, "too many entries in v0 script record");

        let bytes = bytes.remaining_slice();

        let (id, bytes) = decode::read_str_from_slice(bytes).unwrap();
        let (name, bytes) = decode::read_str_from_slice(bytes).unwrap();
        let (description, bytes) = decode::read_str_from_slice(bytes).unwrap();
        let (shebang, bytes) = decode::read_str_from_slice(bytes).unwrap();

        let mut bytes = Bytes::new(bytes);
        let tags_len = decode::read_array_len(&mut bytes).unwrap();

        let mut bytes = bytes.remaining_slice();

        let mut tags = Vec::new();
        for _ in 0..tags_len {
            let (tag, remaining) = decode::read_str_from_slice(bytes).unwrap();
            tags.push(tag.to_owned());
            bytes = remaining;

View on GitHub (pinned to 900007c480)