nautechsystems/nautilus_trader · error

Failed to load instrument closes: {e}

Error message

Failed to load instrument closes: {e}

What it means

Raised by `load_instrument_closes` when the ordered `SELECT * FROM instrument_close` query fails. The sqlx error from `fetch_all` is wrapped in `anyhow` with this message. The caller receives no instrument close history, which typically breaks replay or analysis that depends on close records.

Source

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

        .execute(pool)
        .await
        .map(|_| ())
        .map_err(|e| anyhow::anyhow!("Failed to insert instrument close: {e}"))
    }

    /// Loads all `InstrumentClose` entries.
    ///
    /// # Errors
    ///
    /// Returns an error if the SQL SELECT or row decoding fails.
    pub async fn load_instrument_closes(pool: &PgPool) -> anyhow::Result<Vec<InstrumentClose>> {
        sqlx::query_as::<_, InstrumentCloseRow>(
            "SELECT * FROM instrument_close ORDER BY instrument_id ASC",
        )
        .fetch_all(pool)
        .await
        .map(|rows| rows.into_iter().map(|row| row.0).collect())
        .map_err(|e| anyhow::anyhow!("Failed to load instrument closes: {e}"))
    }

    /// Inserts an `OrderInitialized` event via the provided `pool`.
    ///
    /// # Errors
    ///
    /// Returns an error if the SQL INSERT or UPDATE operation fails.
    pub async fn add_order(
        pool: &PgPool,
        event: OrderInitialized,
        client_id: Option<ClientId>,
    ) -> anyhow::Result<()> {
        Self::add_order_event(pool, Box::new(event), client_id).await
    }

    /// Inserts an `OrderSnapshot` entry via the provided `pool`.
    ///
    /// # Errors

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the wrapped `{e}` text to distinguish connection, schema, and decode failures.
  2. Run the required migrations so `instrument_close` exists.
  3. Check database connectivity and enable pool health checks / reconnection.
  4. If decoding fails, align table column types with `InstrumentCloseRow` (schema or crate version mismatch).

Example fix

// before
let closes = load_instrument_closes(&pool).await?;

// after: retry transient failures
let closes = loop {
    match load_instrument_closes(&pool).await {
        Ok(c) => break c,
        Err(e) if is_transient(&format!("{e:#}")) => {
            tokio::time::sleep(std::time::Duration::from_secs(1)).await;
        }
        Err(e) => return Err(e),
    }
};
Defensive patterns

Strategy: retry

Validate before calling

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

Try / catch

async fn load_closes_with_retry(pool: &PgPool) -> anyhow::Result<Vec<InstrumentClose>> {
    let mut delay = std::time::Duration::from_millis(250);
    loop {
        match load_instrument_closes(pool).await {
            Ok(v) => return Ok(v),
            Err(e) => {
                if !is_transient(&format!("{e:#}")) { return Err(e); }
                tokio::time::sleep(delay).await;
                delay *= 2;
            }
        }
    }
}

Prevention

When it happens

Trigger: Calling `load_instrument_closes(&pool)` when: the `instrument_close` table is missing (migrations not run); the connection is broken or the pool has no connections; a row's column types fail to decode into `InstrumentCloseRow`; or the query is cancelled/times out.

Common situations: Pointing at a fresh database without schema; schema drift after a crate upgrade changing `InstrumentCloseRow` fields; database restart mid-session leaving stale pooled connections; large table causing statement timeout.

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/ece68b5571c371f5. Report an issue: GitHub.