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

  1. Verify `BybitSmpType` still derives `Serialize` and all variants are plain unit variants
  2. Rebuild the extension module after any change to the enum
  3. If a variant is not string-serializable, return the debug/name string instead of JSON round-tripping
  4. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/537249a811c819d3. Report an issue: GitHub.