{"record":{"id":"1b485a33b3687e08","repo":"nautechsystems/nautilus_trader","slug":"expected-1b485a","errorCode":null,"errorMessage":"Expected {}","messagePattern":"Expected (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/serialization/src/arrow/custom.rs","lineNumber":107,"sourceCode":"    let type_name = T::type_name_static();\n\n    // Skip if already registered\n    if get_arrow_schema(type_name).is_some() {\n        return;\n    }\n\n    let _ = ensure_custom_data_json_registered::<T>();\n\n    let schema = Arc::new(T::get_schema(None));\n\n    let encoder: ArrowEncoder = Box::new(|items: &[Arc<dyn CustomDataTrait>]| {\n        let typed: Result<Vec<T>, _> = items\n            .iter()\n            .map(|b| {\n                b.as_any()\n                    .downcast_ref::<T>()\n                    .cloned()\n                    .ok_or_else(|| anyhow::anyhow!(\"Expected {}\", T::type_name_static()))\n            })\n            .collect();\n        let typed = typed?;\n        let metadata = typed\n            .first()\n            .map(EncodeToRecordBatch::metadata)\n            .unwrap_or_default();\n        EncodeToRecordBatch::encode_batch(&metadata, &typed).map_err(|e| anyhow::anyhow!(\"{e}\"))\n    });\n\n    let decoder: ArrowDecoder = Box::new(|metadata, batch| {\n        T::decode_data_batch(metadata, batch).map_err(|e| anyhow::anyhow!(\"{e}\"))\n    });\n\n    let _ = ensure_arrow_registered(type_name, schema, encoder, decoder);\n}\n\n/// Decoder for custom data types that are identified at runtime by metadata (e.g. `type_name`).","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/serialization/src/arrow/custom.rs#L89-L125","documentation":"ensure_custom_data_registered builds an Arrow encoder for a custom data type T by downcasting each Arrow array in the input to the concrete array type T expects. If any element in the batch cannot be downcast to T's expected array type (ArrayRef -> T's array), the registration fails with \"Expected {type_name}\". This is an internal invariant: the batch passed to the encoder must match the registered type's schema.","triggerScenarios":"Registering or encoding custom data where the RecordBatch contains arrays of a different concrete Arrow type than T::EncodeToRecordBatch produces — e.g. schema drift between the writer and the registered encoder, or mixed array types in one batch.","commonSituations":"Custom data structs whose encode implementation changed (field type changed from Int64 to Float64) while old files/streams still use the old schema; passing a batch produced for a different data type into the encoder; version mismatch between serialization code writing the data and code reading it.","solutions":["Ensure the RecordBatch passed to the encoder was produced by the same T's encode implementation (same type_name and schema)","Check for schema drift: if the custom data struct's fields/types changed, re-encode historical data or bump the type/schema identifier","Validate array types before encoding (e.g. assert batch columns downcast to the expected Arrow array types)","Regenerate or update any persisted Arrow files written with the old schema"],"exampleFix":"// before: passing a generic batch to the custom encoder\nensure_custom_data_registered::<MyData>(&batches)?;\n// after: filter batches to those produced for MyData\nlet my_batches: Vec<_> = batches.into_iter().filter(|b| b.schema() == MyData::schema()).collect();\nensure_custom_data_registered::<MyData>(&my_batches)?;","handlingStrategy":"type-guard","validationCode":"fn batch_matches<T: EncodeToRecordBatch>(batch: &RecordBatch) -> bool {\n    batch.columns().iter().all(|c| c.as_any().downcast_ref::<T::Array>().is_some())\n}","typeGuard":"fn as_expected_array<T: 'static>(arr: &dyn Array) -> Option<&T> {\n    arr.as_any().downcast_ref::<T>()\n}","tryCatchPattern":"match ensure_custom_data_registered::<MyData>(...) {\n    Err(e) if e.to_string().starts_with(\"Expected \") => {\n        eprintln!(\"schema mismatch in custom data batch: {e:#}\");\n    }\n    other => other?,\n}","preventionTips":["Keep encode implementations and struct fields in lockstep; add encode round-trip unit tests","Bump type/schema identifiers whenever a custom data struct's field types change","Only feed batches produced by the same type's encoder into the custom registration path"],"tags":["arrow","serialization","downcast","schema"],"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"}