{"record":{"id":"483b09c3094fea8e","repo":"atuinsh/atuin","slug":"too-many-entries-in-v0-script-record","errorCode":null,"errorMessage":"too many entries in v0 script record","messagePattern":"too many entries in v0 script record","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-scripts/src/store/script.rs","lineNumber":69,"sourceCode":"        encode::write_str(&mut output, &self.name)?;\n        encode::write_str(&mut output, &self.description)?;\n        encode::write_str(&mut output, &self.shebang)?;\n        encode::write_array_len(&mut output, u32::conv(self.tags.len()))?;\n\n        for tag in &tags {\n            encode::write_str(&mut output, tag)?;\n        }\n\n        encode::write_str(&mut output, &self.script)?;\n\n        Ok(DecryptedData(output))\n    }\n\n    pub fn deserialize(bytes: &[u8]) -> Result<Self> {\n        let mut bytes = decode::Bytes::new(bytes);\n        let nfields = decode::read_array_len(&mut bytes).unwrap();\n\n        ensure!(nfields == 6, \"too many entries in v0 script record\");\n\n        let bytes = bytes.remaining_slice();\n\n        let (id, bytes) = decode::read_str_from_slice(bytes).unwrap();\n        let (name, bytes) = decode::read_str_from_slice(bytes).unwrap();\n        let (description, bytes) = decode::read_str_from_slice(bytes).unwrap();\n        let (shebang, bytes) = decode::read_str_from_slice(bytes).unwrap();\n\n        let mut bytes = Bytes::new(bytes);\n        let tags_len = decode::read_array_len(&mut bytes).unwrap();\n\n        let mut bytes = bytes.remaining_slice();\n\n        let mut tags = Vec::new();\n        for _ in 0..tags_len {\n            let (tag, remaining) = decode::read_str_from_slice(bytes).unwrap();\n            tags.push(tag.to_owned());\n            bytes = remaining;","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/atuinsh/atuin/blob/c0c717ab04c881764bcad4b3d169a507e2432643/crates/atuin-scripts/src/store/script.rs#L51-L87","documentation":"A v0 script record is a msgpack array with exactly 6 fields (id, name, description, and the remaining script metadata fields). The scripts store deserializer requires the decoded array length to be 6; anything else is rejected as malformed. This enforces the v0 scripts on-wire schema in the record store.","triggerScenarios":"Deserializing a v0 script record whose msgpack payload decodes to an array length other than 6.","commonSituations":"Syncing script records from a client with a different scripts schema version; corrupted record payloads; records created by tooling writing directly to the store.","solutions":["Upgrade atuin on all machines syncing scripts to the same version","Delete the malformed script record and re-add the script via `atuin scripts new`","Re-sync scripts from a known-good machine","Inspect the record store DB row if the corruption is isolated"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let n = rmp::decode::read_array_len(&mut bytes)?;\nif n != 6 { return Err(\"malformed v0 script record\".into()); }","typeGuard":null,"tryCatchPattern":"match Script::deserialize(&data) {\n    Ok(script) => install(script),\n    Err(e) => log::warn!(\"skipping malformed script record: {e}\"),\n}","preventionTips":["Keep script-store clients on matching atuin versions","Re-add scripts via `atuin scripts new` instead of editing records","Avoid external writes to the scripts store","Check records after restoring from a backup"],"tags":["msgpack","deserialization","scripts","record-store","versioning"],"backgroundTag":"schema-validation-failed","analyzedSha":"c0c717ab04c881764bcad4b3d169a507e2432643","analyzedAt":"2026-09-12T07:40:01.341Z","contentChangedAt":"2026-09-12T07:40:01.341Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}