{"record":{"id":"e456cc030380888b","repo":"nautechsystems/nautilus_trader","slug":"no-items-to-encode","errorCode":null,"errorMessage":"No items to encode","messagePattern":"No items to encode","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/python/data/mod.rs","lineNumber":388,"sourceCode":"        Ok(Arc::new(wrapper) as Arc<dyn crate::data::CustomDataTrait>)\n    })\n}\n\n/// Encodes `CustomData` items to `RecordBatch` via Python `encode_record_batch_py`.\n#[allow(unsafe_code)]\n#[cfg(all(feature = \"python\", feature = \"arrow\"))]\nfn py_encode_custom_data_to_record_batch(\n    items: &[std::sync::Arc<dyn crate::data::CustomDataTrait>],\n) -> Result<arrow::record_batch::RecordBatch, anyhow::Error> {\n    pyo3::Python::attach(|py| {\n        let py_items: Result<Vec<_>, _> = items.iter().map(|item| item.to_pyobject(py)).collect();\n        let py_items = py_items.map_err(|e| anyhow::anyhow!(\"Failed to convert to Python: {e}\"))?;\n        let py_list = pyo3::types::PyList::new(py, &py_items)\n            .map_err(|e| anyhow::anyhow!(\"Failed to create list: {e}\"))?;\n\n        let first = items\n            .first()\n            .ok_or_else(|| anyhow::anyhow!(\"No items to encode\"))?;\n        let first_py = first.to_pyobject(py)?;\n\n        if first_py\n            .bind(py)\n            .hasattr(\"encode_record_batch_py\")\n            .unwrap_or(false)\n        {\n            let py_batch = first_py\n                .bind(py)\n                .call_method1(\"encode_record_batch_py\", (py_list,))\n                .map_err(|e| anyhow::anyhow!(\"Failed to call encode_record_batch_py: {e}\"))?;\n\n            let mut ffi_array = arrow::ffi::FFI_ArrowArray::empty();\n            let mut ffi_schema = arrow::ffi::FFI_ArrowSchema::empty();\n\n            py_batch.call_method1(\n                \"_export_to_c\",\n                (","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/python/data/mod.rs#L370-L406","documentation":"The Arrow encode function for custom data requires at least one item: it inspects the first item to discover the Python `encode_record_batch_py` method. If the caller passes an empty slice, this error is returned. It is a guard against encoding a zero-length batch through the Python-side encoder.","triggerScenarios":"Calling the custom-data Arrow encode path (via registered custom data classes) with an empty `items` slice — e.g. encoding an empty list of custom data objects to a RecordBatch.","commonSituations":"A data pipeline forwards an empty collection (no custom data received yet) straight to the catalog writer without checking emptiness; batching logic produces an empty final batch that is still sent to encode.","solutions":["Guard the call site: skip encoding (or produce an empty batch another way) when the collection is empty.","Check `len(items)` before invoking the encode path for custom data.","Fix upstream logic that produces empty batches and ensure they are filtered before persistence."],"exampleFix":"# before\nbatch = encode_custom_data(items)  # raises when items == []\n\n# after\nbatch = encode_custom_data(items) if items else None\nif batch is not None:\n    write(batch)","handlingStrategy":"validation","validationCode":"if not items:\n    return None  # skip encoding empty custom data batches","typeGuard":null,"tryCatchPattern":"if items:\n    batch = encode_to_record_batch(items)\nelse:\n    batch = None","preventionTips":["Filter empty collections before calling any encode path","Handle the empty-batch case explicitly in persistence pipelines","Never rely on the encoder to tolerate zero items"],"tags":["custom-data","arrow","empty-input","validation"],"backgroundTag":"empty-required-field","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"}