{"record":{"id":"dd7e4dda7c716be9","repo":"cocoindex-io/cocoindex","slug":"while-deserializing-full-path-inner","errorCode":null,"errorMessage":"while deserializing `{full_path}`: {inner}","messagePattern":"while deserializing `(.+?)`: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust/utils/src/deser.rs","lineNumber":15,"sourceCode":"use anyhow::{Result, anyhow};\nuse serde::de::DeserializeOwned;\n\nfn format_serde_path_err<T, E: std::fmt::Display>(\n    err: serde_path_to_error::Error<E>,\n) -> anyhow::Error {\n    let ty = std::any::type_name::<T>().replace(\"::\", \".\");\n    let path = err.path();\n    let full_path = if path.iter().next().is_none() {\n        format!(\"<{ty}>\")\n    } else {\n        format!(\"<{ty}>.{path}\")\n    };\n    let inner = err.into_inner();\n    anyhow!(\"while deserializing `{full_path}`: {inner}\")\n}\n\npub fn from_json_value<T: DeserializeOwned>(value: serde_json::Value) -> Result<T> {\n    serde_path_to_error::deserialize::<_, T>(value).map_err(format_serde_path_err::<T, _>)\n}\n\npub fn from_json_str<T: DeserializeOwned>(s: &str) -> Result<T> {\n    let mut de = serde_json::Deserializer::from_str(s);\n    serde_path_to_error::deserialize::<_, T>(&mut de).map_err(format_serde_path_err::<T, _>)\n}\n\npub fn from_msgpack_slice<'a, T: serde::Deserialize<'a>>(data: &'a [u8]) -> Result<T> {\n    let mut de = rmp_serde::Deserializer::from_read_ref(data);\n    serde_path_to_error::deserialize::<_, T>(&mut de).map_err(format_serde_path_err::<T, _>)\n}\n","sourceCodeStart":1,"sourceCodeEnd":31,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/rust/utils/src/deser.rs#L1-L31","documentation":"This is a deserialization error wrapper: serde failed to convert a JSON/value into type T, and cocoindex uses serde_path_to_error to report the exact field path (e.g. `<TargetConfig>.spec.regex`) plus the underlying serde message. It tells you precisely where in the structure the data did not match the expected schema.","triggerScenarios":"Any code path using utils::deser::from_json_value / from_str (loading saved state, target configs, or exported specs) where a field is missing, has the wrong type, or an untagged enum variant fails to match.","commonSituations":"Reading an LMDB/database state written by an older cocoindex version whose schema has since changed (enum variant renamed); hand-edited JSON config with a type typo; passing a serde_json::Value built by another tool with different field names.","solutions":["Fix the field at the reported path: match the type/name expected by the message's `{inner}` part.","If the data came from an older version, re-run the pipeline to regenerate state instead of deserializing stale data.","For hand-written configs, validate against the current struct definitions (or docs) for the target type shown in `<ty>`.","Clear/recreate the corrupted persisted state entry if it cannot be migrated."],"exampleFix":"// before\nfrom_json_value::<Config>(json!({\"chunks\": 3})) // expects chunk_size: u64\n\n// after\nfrom_json_value::<Config>(json!({\"chunk_size\": 3}))","handlingStrategy":"validation","validationCode":"// validate before committing state\nlet cfg: Config = serde_json::from_value(value.clone())\n    .map_err(|e| anyhow!(\"config shape mismatch: {e}\"))?;","typeGuard":null,"tryCatchPattern":"// match on the path-aware error\nmatch deser::from_json_value::<Config>(value) {\n    Ok(cfg) => apply(cfg),\n    Err(e) => {\n        eprintln!(\"{e:#}\"); // shows field path + serde reason\n        // regenerate or migrate the stale state\n    }\n}","preventionTips":["Keep serialized state and struct definitions in the same version; migrate on upgrade.","Never hand-edit persisted JSON/state; regenerate via the pipeline.","Round-trip test new config structs with serde to catch schema drift."],"tags":["rust","serde","deserialization","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}