{"record":{"id":"3e981dd38b3a3511","repo":"atuinsh/atuin","slug":"too-many-entries-in-v0-kv-record","errorCode":null,"errorMessage":"too many entries in v0 kv record","messagePattern":"too many entries in v0 kv record","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/atuin-kv/src/store/record.rs","lineNumber":46,"sourceCode":"            encode::write_str(&mut output, value)?;\n        }\n\n        Ok(DecryptedData(output))\n    }\n\n    pub fn deserialize(data: &DecryptedData, version: &RecordVersion) -> Result<Self> {\n        use rmp::decode;\n\n        fn error_report<E: std::fmt::Debug>(err: E) -> eyre::Report {\n            eyre!(\"{err:?}\")\n        }\n\n        match version {\n            RecordVersion::V0 => {\n                let mut bytes = decode::Bytes::new(&data.0);\n\n                let nfields = decode::read_array_len(&mut bytes).map_err(error_report)?;\n                ensure!(nfields == 3, \"too many entries in v0 kv record\");\n\n                let bytes = bytes.remaining_slice();\n\n                let (namespace, bytes) =\n                    decode::read_str_from_slice(bytes).map_err(error_report)?;\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                if !bytes.is_empty() {\n                    bail!(\"trailing bytes in encoded kvrecord. malformed\");\n                }\n\n                Ok(Self {\n                    namespace: namespace.to_owned(),\n                    key: key.to_owned(),\n                    value: Some(value.to_owned()),\n                })\n            }","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/atuinsh/atuin/blob/900007c48045867e7f44b0f9bc55ad9dbe99ee0d/crates/atuin-kv/src/store/record.rs#L28-L64","documentation":"A v0 KV record must be a MsgPack array of exactly 3 entries: namespace, key, and value. The KV record deserializer checks the array length first and rejects any deviation, so payloads with extra or missing fields cannot be silently misread.","triggerScenarios":"Deserializing a record tagged V0 whose array length != 3 — e.g. encoded by a newer KV schema, written with extra metadata fields, or corrupted in storage.","commonSituations":"KV records synced from clients on different Atuin/KV schema versions, third-party writers to the record store, or truncated/corrupted payloads.","solutions":["Re-write the KV entry with your current client: delete the key and set it again via `atuin kv`.","Fix any custom writer to emit exactly (namespace, key, value) for V0 records, or encode as V1 instead.","Align schema versions across sync peers."],"exampleFix":"// before: encode::to_bytes(&(namespace, key, value, metadata))\n// after:  encode::to_bytes(&(namespace, key, value))","handlingStrategy":"validation","validationCode":"let value: rmpv::Value = rmpv::decode::read_value(&mut cursor)?;\n// v0 kv record requires exactly 3 fields\nassert_eq!(value.as_array().map(|a| a.len()), Some(3));","typeGuard":"fn is_well_formed_v0_kv(payload: &[u8]) -> bool {\n    rmpv::decode::read_value(&mut std::io::Cursor::new(payload))\n        .ok()\n        .and_then(|v| v.as_array().map(|a| a.len() == 3))\n        .unwrap_or(false)\n}","tryCatchPattern":"match KvRecord::deserialize(&data) {\n    Ok(rec) => apply(rec),\n    Err(e) if e.to_string().contains(\"too many entries\") => {\n        log::warn(\"malformed v0 kv record skipped: {e}\");\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Never attach extra metadata to v0 kv records; use the V1 schema if you need more fields","Match the record's version tag to its field count","Keep KV clients on compatible schema versions"],"tags":["serialization","msgpack","kv"],"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"}