nautechsystems/nautilus_trader · error
Failed to load instruments: {e}
Error message
Failed to load instruments: {e} What it means
This error is raised by `load_instruments` in the SQL queries module when the `SELECT * FROM instrument` query against PostgreSQL fails. The library wraps any sqlx error returned by `fetch_all` into an `anyhow::Error` with this message, so the underlying cause (connection issue, missing table, bad column mapping) is embedded in the `{e}` text. It means the instruments could not be read from the database, and the caller receives no instrument data.
Source
Thrown at crates/infrastructure/src/sql/queries.rs:239
.fetch_optional(pool)
.await
.map(|instrument| instrument.map(|row| row.0))
.map_err(|e| {
anyhow::anyhow!("Failed to load instrument with id {instrument_id},error is: {e}")
})
}
/// Loads all `InstrumentAny` entries via the provided `pool`.
///
/// # Errors
///
/// Returns an error if the SELECT operation fails.
pub async fn load_instruments(pool: &PgPool) -> anyhow::Result<Vec<InstrumentAny>> {
sqlx::query_as::<_, InstrumentAnyRow>("SELECT * FROM instrument")
.fetch_all(pool)
.await
.map(|rows| rows.into_iter().map(|row| row.0).collect())
.map_err(|e| anyhow::anyhow!("Failed to load instruments: {e}"))
}
/// Inserts or replaces an `InstrumentClose`.
///
/// # Errors
///
/// Returns an error if the SQL INSERT or UPDATE fails.
pub async fn add_instrument_close(
pool: &PgPool,
close: &InstrumentClose,
) -> anyhow::Result<()> {
sqlx::query(
r#"
INSERT INTO "instrument_close" (
instrument_id, close_price, close_type, ts_event, ts_init, created_at
) VALUES ($1, $2, $3, $4, $5, CURRENT_TIMESTAMP)
ON CONFLICT (instrument_id) DO UPDATE
SET close_price = EXCLUDED.close_price,View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the wrapped `{e}` message to identify the root cause (connection vs missing table vs decode error).
- Run the project's SQL migrations so the `instrument` table exists with the expected schema.
- Verify the PostgreSQL connection string / pool configuration and that the database is reachable.
- If it is a decode/type error, align the database column types with `InstrumentAnyRow` (upgrade schema or crate together).
Example fix
// before: calls the query and panics/unwraps elsewhere
let instruments = load_instruments(&pool).await.unwrap();
// after: handle the error explicitly
let instruments = match load_instruments(&pool).await {
Ok(v) => v,
Err(e) => {
tracing::error!("instrument load failed: {e:#}");
return Err(e);
}
}; Defensive patterns
Strategy: try-catch
Validate before calling
// Before calling: verify DB reachable and table exists
let ok = sqlx::query_scalar::<_, i64>(
"SELECT COUNT(*) FROM information_schema.tables WHERE table_name = 'instrument'")
.fetch_one(pool).await? > 0;
if !ok { return Err(anyhow::anyhow!("instrument table missing: run migrations")); } Try / catch
match load_instruments(&pool).await {
Ok(instruments) => instruments,
Err(e) => {
tracing::error!("load_instruments failed: {e:#}");
return Err(anyhow::anyhow!("instruments unavailable: {e:#}"));
}
} Prevention
- Run SQL migrations as a startup step before any query functions are used.
- Validate DATABASE_URL and connectivity with a `SELECT 1` at application start.
- Keep the crate version and database schema in lockstep when upgrading.
- Enable sqlx logging (`RUST_LOG=sqlx=debug`) to see root-cause errors early.
When it happens
Trigger: Calling `load_instruments(&pool)` when: the database connection is down or the pool is exhausted; the `instrument` table does not exist (migrations not run); a column type in the table does not match `InstrumentAnyRow`'s expected types (sqlx decode failure); or the query times out.
Common situations: Running against a database without the Nautilus schema migrations applied; wrong DATABASE_URL pointing at an empty/unrelated database; schema drift after upgrading the crate where a new/renamed column breaks the row decoding; PostgreSQL temporarily unreachable in a containerized environment.
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
- Failed to load from execution_transaction table: {e}
- Failed to insert instrument close: {e}
- Failed to load instrument closes: {e}
- Failed to insert into trader table: {e}
- Failed to insert into order table: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/31f1a02c6eaba73a.
Report an issue: GitHub.