nautechsystems/nautilus_trader · error · anyhow::Error
Failed to load pool positions: {e}
Error message
Failed to load pool positions: {e} What it means
This wraps a SQLx failure from the SELECT that fetches all liquidity-position rows belonging to a pool snapshot at its watermark (`fetch_all`). The positions cannot be loaded, so snapshot replay/restore aborts. Like the other wrappers, only actual query failures produce this — an empty result set is valid.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:2679
tokens_owed_0::TEXT, tokens_owed_1::TEXT,
total_amount0_deposited::TEXT, total_amount1_deposited::TEXT,
total_amount0_collected::TEXT, total_amount1_collected::TEXT
FROM pool_position
WHERE chain_id = $1
AND pool_identifier = $2
AND snapshot_block = $3
AND snapshot_transaction_index = $4
AND snapshot_log_index = $5
",
)
.bind(chain_id as i32)
.bind(pool_identifier.as_ref())
.bind(snapshot_block as i64)
.bind(snapshot_transaction_index as i32)
.bind(snapshot_log_index as i32)
.fetch_all(&self.pool)
.await
.map_err(|e| anyhow::anyhow!("Failed to load pool positions: {e}"))?;
rows.iter()
.map(|row| {
let owner: String = row.get("owner");
let position = PoolPosition {
owner: validate_address(&owner)?,
tick_lower: row.get("tick_lower"),
tick_upper: row.get("tick_upper"),
liquidity: row.get::<String, _>("liquidity").parse()?,
fee_growth_inside_0_last: row
.get::<String, _>("fee_growth_inside_0_last")
.parse()?,
fee_growth_inside_1_last: row
.get::<String, _>("fee_growth_inside_1_last")
.parse()?,
tokens_owed_0: row.get::<String, _>("tokens_owed_0").parse()?,
tokens_owed_1: row.get::<String, _>("tokens_owed_1").parse()?,
total_amount0_deposited: rowView on GitHub (pinned to 18893faf8b)
Solutions
- Check database reachability and credentials with the same URL the adapter uses.
- Apply pending migrations so the positions table and columns match the adapter's expectations.
- Inspect the chained `{e}` for the precise SQLSTATE/driver cause.
- If timeouts recur on managed Postgres, raise the pool's acquire timeout or reduce concurrent load.
- Verify the `positions` table has indexes on (pool_identifier, snapshot watermark) so large fetches don't time out.
Example fix
// before: no timeout handling
let rows = store.load_positions(...).await?;
// after: guard against transient/network errors
let rows = tokio::time::timeout(Duration::from_secs(30), store.load_positions(...)).await
.map_err(|_| anyhow::anyhow!("positions load timed out"))??; Defensive patterns
Strategy: try-catch
Validate before calling
// confirm schema before loading
sqlx::query("SELECT 1 FROM pool_positions LIMIT 1").execute(&db).await?; Try / catch
match store.load_positions(...).await {
Ok(positions) => positions,
Err(e) if is_timeout_or_transient(&e) => retry_with_backoff(|| store.load_positions(...), 3).await,
Err(e) => return Err(e),
} Prevention
- Run migrations before adapter startup so the positions table exists with expected columns.
- Set explicit acquire/statement timeouts on the sqlx pool sized for your Postgres latency.
- Index positions by (pool_identifier, snapshot watermark) to keep large fetches fast.
- Monitor DB connectivity with health checks and alerts.
When it happens
Trigger: Calling the pool-positions loader when the DB is down, the positions table is missing/renamed (schema drift), bound column types no longer match (e.g. `snapshot_block` column type changed), or connection limits are exhausted.
Common situations: Postgres container stopped or restarted; adapter upgraded without running migrations; wrong database/URL env var pointing at a database without the positions schema; network partition to a remote managed Postgres (timeouts).
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 seed chain table: {e}
- Failed to call create_block_partition for chain {}: {e}
- Failed to call create_token_partition for chain {}: {e}
- Failed to get block info for chain {}: {}
- Failed to insert into block table: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/18532be420f847ed.
Report an issue: GitHub.