{"record":{"id":"160d86b27a9b4819","repo":"nautechsystems/nautilus_trader","slug":"expected","errorCode":null,"errorMessage":"Expected {}","messagePattern":"Expected (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/persistence/macros/src/custom.rs","lineNumber":1161,"sourceCode":"        }\n    };\n    let from_impl = quote! {\n        impl #generics std::convert::From<#name #generics> for nautilus_model::data::Data {\n            fn from(value: #name #generics) -> Self {\n                nautilus_model::data::Data::Custom(nautilus_model::data::CustomData::from_arc(std::sync::Arc::new(value)))\n            }\n        }\n    };\n    let try_from_impl = quote! {\n        impl #generics std::convert::TryFrom<nautilus_model::data::Data> for #name #generics {\n            type Error = anyhow::Error;\n            fn try_from(value: nautilus_model::data::Data) -> std::result::Result<Self, Self::Error> {\n                match value {\n                    nautilus_model::data::Data::Custom(custom) => {\n                        if let Some(c) = custom.data.as_any().downcast_ref::<Self>() {\n                            Ok(std::clone::Clone::clone(c))\n                        } else {\n                            anyhow::bail!(\"Expected {}\", #name_str)\n                        }\n                    }\n                    _ => anyhow::bail!(\"Expected Custom data variant\"),\n                }\n            }\n        }\n    };\n    (catalog_path_prefix_impl, from_impl, try_from_impl)\n}\n\n#[expect(\n    clippy::too_many_lines,\n    reason = \"PyO3 token generation is clearer with related methods kept together\"\n)]\nfn gen_pymethods_impl(ctx: &ExpansionContext<'_>) -> TokenStream {\n    let name = ctx.name;\n    let generics = ctx.generics;\n    let field_list = ctx.field_list;","sourceCodeStart":1143,"sourceCodeEnd":1179,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/persistence/macros/src/custom.rs#L1143-L1179","documentation":"Generated by the `#[custom_data]` macro's `TryFrom<Data>` impl: a `Data::Custom` wrapper was downcast to the concrete type but `as_any().downcast_ref::<Self>()` returned None, meaning the boxed payload is a different concrete type than the impl targets. The macro bails to signal a failed downcast during enum-to-concrete conversion. It indicates type confusion between what was wrapped and what is being unwrapped.","triggerScenarios":"Calling `try_from(Data::Custom(...))` (or `TryInto`/record decoding paths that use it) where the inner payload's `type_id` does not match the target struct, e.g. two distinct custom types share the same registered type name, or a serialized type was re-registered under a different Rust type in the process.","commonSituations":"Macro-generated catalog round-trips where a custom data type was registered twice under the same `type_name` with different structs; decoding a Parquet file written by a different version of the struct; mixing custom data types from different crates in one catalog session.","solutions":["Ensure each custom type has a unique `type_name`/identifier in its `#[custom_data]` registration.","Verify the same binary/struct version reads the file that wrote it; re-generate code with the current macro expansion.","Match on `Data::Custom` and log `custom.data.type_name()` before downcasting to identify the actual payload type.","If types legitimately differ, route to the correct `TryFrom` impl instead of forcing this one."],"exampleFix":"// before\nlet typed = MyType::try_from(data)?;\n// after\nlet typed = match &data {\n    nautilus_model::data::Data::Custom(c) if c.data.type_name() == MyType::type_name() =>\n        MyType::try_from(data.clone())?,\n    other => anyhow::bail!(\"unexpected data: {}\", other),\n};","handlingStrategy":"type-guard","validationCode":"fn is_my_type(data: &nautilus_model::data::Data) -> bool {\n    matches!(data, nautilus_model::data::Data::Custom(c)\n        if c.data.as_any().is::<MyType>())\n}","typeGuard":"fn as_my_type(data: &nautilus_model::data::Data) -> Option<&MyType> {\n    match data {\n        nautilus_model::data::Data::Custom(c) => c.data.as_any().downcast_ref::<MyType>(),\n        _ => None,\n    }\n}","tryCatchPattern":"match MyType::try_from(data) {\n    Ok(t) => handle(t),\n    Err(e) if e.to_string().starts_with(\"Expected \") => skip_or_log(data),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Keep one unique type_name per custom struct registration","Downcast-check with `is::<T>()` before calling the generated TryFrom","Round-trip test every custom type in CI to catch registration collisions"],"tags":["rust","downcast","type-mismatch","macros","persistence"],"backgroundTag":"type-mismatch","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}