nautechsystems/nautilus_trader · error

Failed to assemble order {client_order_id} from events: {e}

Error message

Failed to assemble order {client_order_id} from events: {e}

What it means

load_order fetched order event rows from the database but OrderAny::from_events could not rebuild an Order from the event stream. The underlying deserialization/reassembly error is wrapped in this message with the client_order_id for context. It indicates the persisted event log for that order is corrupt, incomplete, or from an incompatible schema/version.

Source

Thrown at crates/infrastructure/src/sql/queries.rs:801

    /// Loads and assembles a complete `OrderAny` for a `client_order_id` via the provided `pool`.
    ///
    /// # Errors
    ///
    /// Returns an error if assembling events or SQL operations fail.
    pub async fn load_order(
        pool: &PgPool,
        client_order_id: &ClientOrderId,
    ) -> anyhow::Result<Option<OrderAny>> {
        let order_events = Self::load_order_events(pool, client_order_id).await;

        match order_events {
            Ok(order_events) => {
                if order_events.is_empty() {
                    return Ok(None);
                }
                let order = OrderAny::from_events(order_events).map_err(|e| {
                    anyhow::anyhow!("Failed to assemble order {client_order_id} from events: {e}")
                })?;
                Ok(Some(order))
            }
            Err(e) => anyhow::bail!("Failed to load order events: {e}"),
        }
    }

    /// Loads and assembles all `OrderAny` entries via the provided `pool`.
    ///
    /// # Errors
    ///
    /// Returns an error if loading events or SQL operations fail.
    pub async fn load_orders(pool: &PgPool) -> anyhow::Result<Vec<OrderAny>> {
        let mut orders: Vec<OrderAny> = Vec::new();
        let client_order_ids: Vec<ClientOrderId> = sqlx::query(
            r#"
            SELECT DISTINCT client_order_id FROM "order_event"
        "#,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the wrapped inner error in the message to identify the exact failing event and field.
  2. Dump the order_event rows for that client_order_id and verify the first event is an OrderInitialized and ordering by ts_init/event_id is correct.
  3. Check whether the rows were written by a different nautilus version; re-import or migrate the data to the current event schema.
  4. Delete/re-load the affected order from the original source of truth, or remove the corrupt rows if the order can be discarded.

Example fix

// before
let order = DatabaseQuery::load_order(&pool, &client_order_id).await?;
// after
match DatabaseQuery::load_order(&pool, &client_order_id).await {
    Ok(order) => order,
    Err(e) if e.to_string().contains("Failed to assemble order") => {
        tracing::error!("Corrupt event log for {client_order_id}: {e:#}");
        None // skip or re-ingest this order
    }
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: try-catch

Type guard

fn is_assembly_error(e: &anyhow::Error) -> bool {
    e.to_string().contains("Failed to assemble order")
}

Try / catch

match load_order(pool, &client_order_id).await {
    Ok(order) => order,
    Err(e) if is_assembly_error(&e) => {
        tracing::error!("order event log corrupt: {e:#}");
        None
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling DatabaseQuery::load_order(pool, &client_order_id) where the rows for the order deserialize fine individually but OrderAny::from_events fails, e.g. first event is not an OrderInitialized, events are out of order, or an event field fails serde deserialization.

Common situations: Events written by an older nautilus version whose event schema changed (renamed/retyped JSON fields); manually edited or partially deleted order_event rows; events for one order mixed with another due to a wrong client_order_id index; truncated inserts from a previously failed transaction.

Related errors


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