nautechsystems/nautilus_trader · info
Failed to serialize BybitSmpType
Error message
Failed to serialize BybitSmpType
What it means
The PyO3 getter `BybitOrder.smp_type()` serializes the `BybitSmpType` enum to JSON with `serde_json::to_string(...).expect(...)`, then strips the surrounding quotes. Serialization of a field-less enum cannot fail under normal operation (the code even carries a `clippy::missing_panics_doc` exemption asserting this), so the panic would indicate a corrupted internal state or a non-serializable enum variant introduced by a change.
Source
Thrown at crates/adapters/bybit/src/http/models.rs:1129
pub fn reduce_only(&self) -> bool {
self.reduce_only
}
#[getter]
#[must_use]
pub fn close_on_trigger(&self) -> bool {
self.close_on_trigger
}
#[getter]
#[must_use]
#[expect(
clippy::missing_panics_doc,
reason = "serialization of a simple enum cannot fail"
)]
pub fn smp_type(&self) -> String {
serde_json::to_string(&self.smp_type)
.expect("Failed to serialize BybitSmpType")
.trim_matches('"')
.to_string()
}
#[getter]
#[must_use]
pub fn smp_group(&self) -> i32 {
self.smp_group
}
#[getter]
#[must_use]
pub fn smp_order_id(&self) -> &str {
self.smp_order_id.as_str()
}
#[getter]
#[must_use]View on GitHub (pinned to 18893faf8b)
Solutions
- Verify `BybitSmpType` still derives `Serialize` and all variants are plain unit variants
- Rebuild the extension module after any change to the enum
- If a variant is not string-serializable, return the debug/name string instead of JSON round-tripping
- Report upstream if the panic occurs on an unmodified build
Example fix
// before
serde_json::to_string(&self.smp_type).expect("Failed to serialize BybitSmpType").trim_matches('"').to_string()
// after
self.smp_type.to_string() // or map_err into a PythonError and return Result<...> Defensive patterns
Strategy: type-guard
Type guard
// Rust: ensure the enum is a unit-only enum before JSON round-tripping
fn is_unit_variant(v: &BybitSmpType) -> bool { matches!(v, BybitSmpType::None | BybitSmpType::Cancel | BybitSmpType::ReduceOnly) } Try / catch
// Python side: wrap getter access defensively
try:
smp = order.smp_type
except Exception as e:
smp = None # and report the deserialization issue Prevention
- Do not hand-edit serde derives on BybitSmpType; change via the generator/source
- Prefer Display/to_string over JSON round-trip for unit enums in PyO3 getters
- Add a unit test covering smp_type() for every enum variant
When it happens
Trigger: Practically unreachable; would require `BybitSmpType` to gain a variant/representation that serde cannot serialize (e.g. a non-string-serializable variant) or corrupted memory. Could surface after a hand-edit of the enum that breaks its serde derive.
Common situations: Reproducing after modifying `BybitSmpType` (adding variants without proper serde attributes); calling the Python getter `order.smp_type` on a deserialized order object.
Understand the failure class
Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.
Related errors
- Failed to convert batched deltas to Python: {e}
- serialized enum variant was not an object
- Invalid NodeState value
- Invalid `ConnectionMode` value: {value}
- BinanceFuturesExecutionClient requires UsdM or CoinM product
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/537249a811c819d3.
Report an issue: GitHub.