nautechsystems/nautilus_trader · error · anyhow::Error

Failed to load pools: {e}

Error message

Failed to load pools: {e}

What it means

Wraps a failed SELECT of all pool rows for a given chain and DEX from the `pool` table (ordered by creation_block). The database error is re-thrown as this anyhow error, so only SQL-execution failures (not empty results) trigger it.

Source

Thrown at crates/adapters/blockchain/src/cache/database.rs:1359

    /// Loads pool data from the database for the specified chain and DEX.
    ///
    /// # Errors
    ///
    /// Returns an error if the database query fails, the connection to the database is lost, or the query parameters are invalid.
    pub async fn load_pools(
        &self,
        chain: SharedChain,
        dex_id: &str,
    ) -> anyhow::Result<Vec<PoolRow>> {
        sqlx::query_as::<_, PoolRow>(AssertSqlSafe(format!(
            "SELECT {POOL_ROW_COLUMNS} FROM pool WHERE chain_id = $1 AND dex_name = $2 ORDER BY creation_block ASC"
        )))
        .bind(chain.chain_id as i32)
        .bind(dex_id)
        .fetch_all(&self.pool)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to load pools: {e}"))
    }

    /// Loads a single pool row by its identifier.
    ///
    /// Returns `None` when the pool is not present in the database. Lets per-pool tools load only
    /// the pool they analyze instead of the whole DEX pool set (see [`load_pools`]).
    ///
    /// [`load_pools`]: Self::load_pools
    ///
    /// # Errors
    ///
    /// Returns an error if the database query fails.
    pub async fn load_pool(
        &self,
        chain: SharedChain,
        dex_id: &str,
        pool_identifier: &PoolIdentifier,
    ) -> anyhow::Result<Option<PoolRow>> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the embedded Postgres error for 'relation does not exist' and run `sqlx migrate run`.
  2. Verify the DATABASE_URL points at the intended database for the target chain/dex data.
  3. If timeouts occur on large pool sets, add pagination or index support on (chain_id, dex_name).
  4. Retry on transient connection errors; ensure the pool has healthy connections.

Example fix

// before: load all pools at once
.fetch_all(&self.pool).await
.map_err(|e| anyhow::anyhow!("Failed to load pools: {e}"))
// after: constrain with an index-friendly query and pagination
// SELECT ... WHERE chain_id = $1 AND dex_name = $2 ORDER BY creation_block ASC LIMIT $3 OFFSET $4;
Defensive patterns

Strategy: retry

Validate before calling

// verify schema readiness before bulk pool loads
let ready: Option<(i64,)> = sqlx::query_as(
    "SELECT 1 FROM information_schema.tables WHERE table_name = 'pool'",
).fetch_optional(&pool).await?;
if ready.is_none() { return Err(anyhow!("pool table missing; run migrations first")); }

Try / catch

let pools = backoff::retry(3, Duration::from_secs(2), || self.load_pools(chain, dex)).await
    .map_err(|e| anyhow!("pool load failed after retries: {e}"))?;

Prevention

When it happens

Trigger: Calling `load_pools` when the fetch_all fails: unknown table/column (POOOL_ROW_COLUMNS vs deployed schema mismatch), connection refused/dropped, statement timeout, or invalid dex_id binding.

Common situations: Starting the app before migrations ran so the `pool` table is missing; pointing the adapter at the wrong database for the environment; long-running query timing out on very large pool sets.

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