nautechsystems/nautilus_trader · error
No items to encode
Error message
No items to encode
What it means
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.
Source
Thrown at crates/model/src/python/data/mod.rs:388
Ok(Arc::new(wrapper) as Arc<dyn crate::data::CustomDataTrait>)
})
}
/// Encodes `CustomData` items to `RecordBatch` via Python `encode_record_batch_py`.
#[allow(unsafe_code)]
#[cfg(all(feature = "python", feature = "arrow"))]
fn py_encode_custom_data_to_record_batch(
items: &[std::sync::Arc<dyn crate::data::CustomDataTrait>],
) -> Result<arrow::record_batch::RecordBatch, anyhow::Error> {
pyo3::Python::attach(|py| {
let py_items: Result<Vec<_>, _> = items.iter().map(|item| item.to_pyobject(py)).collect();
let py_items = py_items.map_err(|e| anyhow::anyhow!("Failed to convert to Python: {e}"))?;
let py_list = pyo3::types::PyList::new(py, &py_items)
.map_err(|e| anyhow::anyhow!("Failed to create list: {e}"))?;
let first = items
.first()
.ok_or_else(|| anyhow::anyhow!("No items to encode"))?;
let first_py = first.to_pyobject(py)?;
if first_py
.bind(py)
.hasattr("encode_record_batch_py")
.unwrap_or(false)
{
let py_batch = first_py
.bind(py)
.call_method1("encode_record_batch_py", (py_list,))
.map_err(|e| anyhow::anyhow!("Failed to call encode_record_batch_py: {e}"))?;
let mut ffi_array = arrow::ffi::FFI_ArrowArray::empty();
let mut ffi_schema = arrow::ffi::FFI_ArrowSchema::empty();
py_batch.call_method1(
"_export_to_c",
(View on GitHub (pinned to 18893faf8b)
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.
Example fix
# before
batch = encode_custom_data(items) # raises when items == []
# after
batch = encode_custom_data(items) if items else None
if batch is not None:
write(batch) Defensive patterns
Strategy: validation
Validate before calling
if not items:
return None # skip encoding empty custom data batches Try / catch
if items:
batch = encode_to_record_batch(items)
else:
batch = None Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- No symbols provided
- At least one --address or --addresses-file entry is required
- Quote maps must not be empty
- Continuous future `bar_types` request parameter must not be
- Instances must have encode_record_batch_py method
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/e456cc030380888b.
Report an issue: GitHub.