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 NOTHINGView on GitHub (pinned to 18893faf8b)
Solutions
- Distinguish this from a missing record: `Ok(None)` means not found, this error means the query failed.
- Inspect the wrapped `{e}` to find the root cause (relation missing, decode error, connection).
- Run the schema migrations and keep the crate version and DB schema in sync.
- 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
- Never conflate Ok(None) with an error — only Err indicates a failed query.
- Run migrations and keep row structs aligned with the schema.
- Use pool acquire timeouts to fail fast on connectivity issues.
- Enable sqlx statement logging during development to catch decode mismatches.
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
- Failed to load instrument closes: {e}
- Failed to load from execution_transaction table: {e}
- Failed to load general table: {e}
- Failed to load currencies: {e}
- Failed to load currency: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/60a307fd16fedcd6.
Report an issue: GitHub.