nautechsystems/nautilus_trader · error

Failed to load order snapshot: {e}

Error message

Failed to load order snapshot: {e}

What it means

Raised by `load_order_snapshot` when the parameterized `SELECT * FROM "order" WHERE client_order_id = $1` query fails. Note this is NOT the 'order not found' case — a missing order returns `Ok(None)`. This error means the query itself failed (connection, schema, or decode problem), wrapped in `anyhow` with this message.

Source

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

            .await
            .map_err(|e| anyhow::anyhow!("Failed to commit transaction: {e}"))
    }

    /// Loads an `OrderSnapshot` entry by client order ID via the provided `pool`.
    ///
    /// # Errors
    ///
    /// Returns an error if the SQL SELECT or deserialization fails.
    pub async fn load_order_snapshot(
        pool: &PgPool,
        client_order_id: &ClientOrderId,
    ) -> anyhow::Result<Option<OrderSnapshot>> {
        sqlx::query_as::<_, OrderSnapshotRow>(r#"SELECT * FROM "order" WHERE client_order_id = $1"#)
            .bind(client_order_id.to_string())
            .fetch_optional(pool)
            .await
            .map(|row| row.map(|row| row.0))
            .map_err(|e| anyhow::anyhow!("Failed to load order snapshot: {e}"))
    }

    /// Inserts or updates a `PositionSnapshot` entry via the provided `pool`.
    ///
    /// # Errors
    ///
    /// Returns an error if the SQL INSERT or UPDATE operation fails, or if beginning the transaction fails.
    pub async fn add_position_snapshot(
        pool: &PgPool,
        snapshot: PositionSnapshot,
    ) -> anyhow::Result<()> {
        let mut transaction = pool.begin().await?;

        // Insert trader if it does not exist
        // TODO remove this when node and trader initialization is implemented
        sqlx::query(
            r#"
            INSERT INTO "trader" (id) VALUES ($1) ON CONFLICT (id) DO NOTHING

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Distinguish this from a missing record: `Ok(None)` means not found, this error means the query failed.
  2. Inspect the wrapped `{e}` to find the root cause (relation missing, decode error, connection).
  3. Run the schema migrations and keep the crate version and DB schema in sync.
  4. Verify pool health / reconnect settings so stale connections are detected.

Example fix

// before: treating None and error the same
let snap = load_order_snapshot(&pool, cid).await.unwrap_or_default();

// after: handle both outcomes explicitly
match load_order_snapshot(&pool, cid).await? {
    Some(snap) => replay(snap),
    None => tracing::warn!("no snapshot for {cid}"),
}
Defensive patterns

Strategy: type-guard

Validate before calling

let ok = sqlx::query_scalar::<_, i64>(
    "SELECT COUNT(*) FROM information_schema.tables WHERE table_name = 'order'")
    .fetch_one(pool).await? > 0;
if !ok { return Err(anyhow::anyhow!("order table missing: run migrations")); }

Type guard

// Distinguish 'query failed' from 'order not found' at the call site
enum SnapshotLookup { Found(OrderSnapshot), NotFound, QueryFailed(anyhow::Error) }
let result = match load_order_snapshot(&pool, client_order_id).await {
    Ok(Some(s)) => SnapshotLookup::Found(s),
    Ok(None) => SnapshotLookup::NotFound,
    Err(e) => SnapshotLookup::QueryFailed(e),
};

Try / catch

match load_order_snapshot(&pool, cid).await {
    Ok(Some(s)) => handle(s),
    Ok(None) => tracing::debug!("no snapshot for {cid}"),
    Err(e) => return Err(anyhow::anyhow!("snapshot lookup failed: {e:#}")),
}

Prevention

When it happens

Trigger: Calling `load_order_snapshot(pool, client_order_id)` when: the connection is unhealthy; the `"order"` table does not exist; the row's columns cannot decode into `OrderSnapshotRow` (schema drift); or the query times out.

Common situations: Fresh/unmigrated database; crate upgrade changed `OrderSnapshotRow` fields while the DB schema is old; pooled stale connections after a DB restart; quoting issues if the table name was created without double quotes in a different tool.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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