nautechsystems/nautilus_trader · error · anyhow::Error
Failed to load signals: {e}
Error message
Failed to load signals: {e} What it means
Raised by `load_signals` when the SELECT of all `signal` rows filtered by `name` fails at the database level. The raw sqlx error is wrapped with `anyhow::anyhow!` and this message; it does not indicate missing rows (that returns an empty vec), only that the query itself failed.
Source
Thrown at crates/infrastructure/src/sql/queries.rs:1608
.await
.map(|_| ())
.map_err(|e| anyhow::anyhow!("Failed to insert into signal table: {e}"))
}
/// Loads all `Signal` entries by `name` via the provided `pool`.
///
/// # Errors
///
/// Returns an error if the SQL SELECT or deserialization fails.
pub async fn load_signals(pool: &PgPool, name: &str) -> anyhow::Result<Vec<Signal>> {
sqlx::query_as::<_, SignalRow>(
r#"SELECT * FROM "signal" WHERE name = $1 ORDER BY ts_init ASC"#,
)
.bind(name)
.fetch_all(pool)
.await
.map(|rows| rows.into_iter().map(|row| row.0).collect())
.map_err(|e| anyhow::anyhow!("Failed to load signals: {e}"))
}
/// Inserts a `CustomData` entry via the provided `pool`.
///
/// Serializes the model `CustomData` to full JSON and stores it in the JSONB `value` column.
///
/// # Errors
///
/// Returns an error if the SQL INSERT operation fails.
pub async fn add_custom_data(pool: &PgPool, data: &CustomData) -> anyhow::Result<()> {
let json_bytes = serde_json::to_vec(data)
.map_err(|e| anyhow::anyhow!("CustomData must be valid JSON: {e}"))?;
let value_json: serde_json::Value = serde_json::from_slice(&json_bytes)
.map_err(|e| anyhow::anyhow!("CustomData value must be valid JSON: {e}"))?;
let data_type_obj = value_json
.get("data_type")
.and_then(|v| v.as_object())
.ok_or_else(|| anyhow::anyhow!("CustomData JSON missing data_type"))?;View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the wrapped sqlx error message for the DB-level cause.
- Ensure migrations created the `signal` table with a `name` column.
- Verify the pool points to the expected database.
- Add retry logic for transient connection failures.
Defensive patterns
Strategy: retry
Validate before calling
let exists: bool = sqlx::query_scalar(
"SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'signal')")
.fetch_one(pool).await?;
anyhow::ensure!(exists, "signal table missing; run migrations"); Try / catch
let signals = retry_backoff(3, || load_signals(&pool, name.clone())).await
.map_err(|e| e.context("loading signals failed after retries"))?; Prevention
- Apply migrations before querying
- Verify pool points at the expected database
- Add bounded retries for transient network errors
- Monitor PostgreSQL restarts
When it happens
Trigger: Calling `load_signals(pool, name)` when the `signal` table doesn't exist, the connection fails, pool is exhausted, or the query text/columns mismatch the current schema.
Common situations: Migrations not applied; using a pool pointing at the wrong database; transient network drops; PostgreSQL restart during the query.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- Failed to load block timestamps: {e}
- Failed to number verified action evidence: {e}
- Failed to inspect recoverable signed executions: {e}
- Failed to load execution transaction hashes: {e}
- Failed to load bars: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/cc543a8c76c8899c.
Report an issue: GitHub.