{"record":{"id":"9cdcddce087fa151","repo":"atuinsh/atuin","slug":"trailing-bytes-in-encoded-dotfiles-env-record-mal","errorCode":null,"errorMessage":"trailing bytes in encoded dotfiles env record, malformed","messagePattern":"trailing bytes in encoded dotfiles env record, malformed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-dotfiles/src/shell.rs","lineNumber":65,"sourceCode":"\n        let nfields = decode::read_array_len(bytes).map_err(error_report)?;\n\n        ensure!(\n            nfields == 3,\n            \"too many entries in v0 dotfiles env create record, got {}, expected {}\",\n            nfields,\n            3\n        );\n\n        let bytes = bytes.remaining_slice();\n\n        let (key, bytes) = decode::read_str_from_slice(bytes).map_err(error_report)?;\n        let (value, bytes) = decode::read_str_from_slice(bytes).map_err(error_report)?;\n\n        let mut bytes = decode::Bytes::new(bytes);\n        let export = decode::read_bool(&mut bytes).map_err(error_report)?;\n\n        ensure!(\n            bytes.remaining_slice().is_empty(),\n            \"trailing bytes in encoded dotfiles env record, malformed\"\n        );\n\n        Ok(Self {\n            name: key.to_owned(),\n            value: value.to_owned(),\n            export,\n        })\n    }\n}\n\n#[must_use]\npub fn parse_alias(line: &str) -> Option<Alias> {\n    // consider the fact we might be importing a fish alias\n    // 'alias' output\n    // fish: alias foo bar\n    // posix: foo=bar","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/atuinsh/atuin/blob/c0c717ab04c881764bcad4b3d169a507e2432643/crates/atuin-dotfiles/src/shell.rs#L47-L83","documentation":"After reading the name, value, and export flag from a v0 dotfiles env record, the decoder requires the byte slice to be fully consumed. Leftover bytes mean the payload has more data than the v0 schema defines, so it is treated as malformed and rejected. This protects against truncated/corrupted or future-format records.","triggerScenarios":"Deserializing a v0 dotfiles env record whose msgpack payload still has remaining bytes after reading key, value, and the boolean export flag.","commonSituations":"Corrupted sync payloads; records written by a newer schema synced into an older client; tampered or partially-written record store data.","solutions":["Upgrade all atuin clients to the latest version so record formats match","Delete the malformed record from the record store and re-create the env var","Verify sync integrity by re-syncing from a machine with correct data","Check disk health / DB integrity if corruption recurs"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// ensure payload is fully consumed by the schema before trusting it\nlet mut b = rmp::decode::Bytes::new(&payload);\n// ...read all 3 fields...\nif !b.remaining_slice().is_empty() { return Err(\"trailing bytes\".into()); }","typeGuard":null,"tryCatchPattern":"match DotfileEnvRecord::deserialize(&data) {\n    Ok(rec) => apply(rec),\n    Err(e) => log::warn!(\"dropping malformed env record: {e}\"),\n}","preventionTips":["Upgrade all clients together when the record format changes","Avoid third-party tools writing to the record store","Re-sync from a healthy host if corruption appears","Monitor sync for records that repeatedly fail to decode"],"tags":["msgpack","deserialization","dotfiles","record-store","trailing-data"],"backgroundTag":"unexpected-response-shape","analyzedSha":"c0c717ab04c881764bcad4b3d169a507e2432643","analyzedAt":"2026-09-12T07:40:01.341Z","contentChangedAt":"2026-09-12T07:40:01.341Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}