{"record":{"id":"ed51117416455b0d","repo":"atuinsh/atuin","slug":"trailing-bytes-in-encoded-script-record-malformed","errorCode":null,"errorMessage":"trailing bytes in encoded script record. malformed","messagePattern":"trailing bytes in encoded script record\\. malformed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-scripts/src/store/script.rs","lineNumber":93,"sourceCode":"        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;\n        }\n\n        let (script, bytes) = decode::read_str_from_slice(bytes).unwrap();\n\n        if !bytes.is_empty() {\n            bail!(\"trailing bytes in encoded script record. malformed\");\n        }\n\n        Ok(Self {\n            id: Uuid::parse_str(id).unwrap(),\n            name: name.to_owned(),\n            description: description.to_owned(),\n            shebang: shebang.to_owned(),\n            tags,\n            script: script.to_owned(),\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/atuinsh/atuin/blob/900007c48045867e7f44b0f9bc55ad9dbe99ee0d/crates/atuin-scripts/src/store/script.rs#L75-L111","documentation":"The script record decoder reads id, name, description, and finally the script body as length-prefixed strings, then requires the payload to be fully consumed. Remaining bytes indicate the payload does not match the expected script record layout, so it bails. This guards the binary format contract.","triggerScenarios":"Deserializing a script record payload with trailing bytes after the script body — corrupted record data, encoder/decoder layout drift, or the wrong payload type passed to this decoder.","commonSituations":"Corrupted local record store; decode mismatch after a scripts format change; syncing partial or damaged records.","solutions":["Delete and re-save the affected script so it is re-encoded cleanly","Verify encoder and decoder agree on field order and length prefixes","Check the record tag is a script record before decoding"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Ensure the payload decodes to four strings (id, name, description, script) with no leftovers\n// fn plausible_script_record(payload: &[u8]) -> bool {\n//     let mut b = payload;\n//     for _ in 0..4 {\n//         match decode::read_str_from_slice(b) { Ok((_, r)) => b = r, Err(_) => return false }\n//     }\n//     b.is_empty()\n// }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid editing script records directly in the store","Re-save scripts that fail to decode so they are re-encoded","Ensure encoder and decoder field order matches within a version"],"tags":["deserialization","scripts","malformed-data"],"backgroundTag":"schema-validation-failed","analyzedSha":"900007c48045867e7f44b0f9bc55ad9dbe99ee0d","analyzedAt":"2026-09-19T12:52:51.491Z","contentChangedAt":"2026-09-19T12:52:51.491Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}