{"record":{"id":"49a73cf74c02d6d3","repo":"nautechsystems/nautilus_trader","slug":"expected-custom-data-variant","errorCode":null,"errorMessage":"Expected Custom data variant","messagePattern":"Expected Custom data variant","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/persistence/macros/src/custom.rs","lineNumber":1164,"sourceCode":"        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;\n    if !ctx.options.pyo3 {\n        return quote! {};\n    }","sourceCodeStart":1146,"sourceCodeEnd":1182,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/persistence/macros/src/custom.rs#L1146-L1182","documentation":"Generated by the `#[custom_data]` macro's `TryFrom<Data>` impl: the incoming `Data` enum was not the `Custom` variant at all (e.g. `Data::Instrument`, `Data::Trade`, `Data::OrderBookDeltas`), so conversion to the concrete custom type is impossible. The macro bails early instead of attempting a downcast on a non-custom payload.","triggerScenarios":"Passing a standard (non-custom) `Data` enum value into a macro-generated `TryFrom<T>` for a custom data type, e.g. feeding quote/trade data into a custom-data decode path or reading a buffer that mixes standard and custom data into the wrong consumer.","commonSituations":"A caller iterating a mixed `Data` buffer assumes all elements are its custom type; misrouted message channels delivering standard market data to a custom-data handler; test fixtures populating buffers with the wrong variant.","solutions":["Match on the `Data` enum first and only convert `Data::Custom` payloads; handle other variants separately.","Filter or partition the buffer by variant/type before attempting the custom conversion.","Check upstream code that constructs the `Data` values to confirm the correct variant is produced."],"exampleFix":"// before\nlet typed = MyType::try_from(data)?;\n// after\nlet typed = match data {\n    nautilus_model::data::Data::Custom(_) => MyType::try_from(data)?,\n    _ => return Ok(None), // skip non-custom data\n};","handlingStrategy":"type-guard","validationCode":"fn is_custom(data: &nautilus_model::data::Data) -> bool {\n    matches!(data, nautilus_model::data::Data::Custom(_))\n}","typeGuard":"fn as_custom(data: &nautilus_model::data::Data) -> Option<&nautilus_model::data::CustomData> {\n    match data {\n        nautilus_model::data::Data::Custom(c) => Some(c),\n        _ => None,\n    }\n}","tryCatchPattern":"match MyType::try_from(data) {\n    Ok(t) => handle(t),\n    Err(e) if e.to_string() == \"Expected Custom data variant\" => Ok(()), // expected skip\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Filter buffers by `Data` variant before custom conversion","Keep custom and standard data on separate channels/buffers","Assert buffer homogeneity in tests"],"tags":["rust","enum","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"}