nautechsystems/nautilus_trader · error
Failed to load currencies: {e}
Error message
Failed to load currencies: {e} What it means
`DatabaseQueries::load_currencies` runs `SELECT * FROM currency ORDER BY id ASC`, decodes each row into a `Currency`, and wraps any sqlx failure in this anyhow error. Failure means execution or decoding failed: connectivity, missing table, or rows containing `currency_type` enum values written by a different version that this binary's decoder cannot understand.
Source
Thrown at crates/infrastructure/src/sql/queries.rs:128
.bind(currency.name.as_str())
.bind(CurrencyTypePg(currency.currency_type))
.execute(pool)
.await
.map(|_| ())
.map_err(|e| anyhow::anyhow!("Failed to insert into currency table: {e}"))
}
/// Loads all `Currency` entries via the provided `pool`.
///
/// # Errors
///
/// Returns an error if the SELECT operation fails.
pub async fn load_currencies(pool: &PgPool) -> anyhow::Result<Vec<Currency>> {
sqlx::query_as::<_, CurrencyRow>("SELECT * FROM currency ORDER BY id ASC")
.fetch_all(pool)
.await
.map(|rows| rows.into_iter().map(|row| row.0).collect())
.map_err(|e| anyhow::anyhow!("Failed to load currencies: {e}"))
}
/// Loads a single `Currency` entry by `code` via the provided `pool`.
///
/// # Errors
///
/// Returns an error if the SELECT operation fails.
pub async fn load_currency(pool: &PgPool, code: &str) -> anyhow::Result<Option<Currency>> {
sqlx::query_as::<_, CurrencyRow>("SELECT * FROM currency WHERE id = $1")
.bind(code)
.fetch_optional(pool)
.await
.map(|currency| currency.map(|row| row.0))
.map_err(|e| anyhow::anyhow!("Failed to load currency: {e}"))
}
/// Inserts or updates an `InstrumentAny` entry via the provided `pool`.
///View on GitHub (pinned to 18893faf8b)
Solutions
- Run matching migrations so the `currency` table and enum values align with this code version.
- Align writer/reader versions so all stored currency_type values are decodable, or re-write offending rows with the current version.
- Check DATABASE_URL points at the intended cache database.
- Read the inner sqlx error to distinguish 'relation does not exist' (migrations) from 'error decoding' (data/schema drift).
Defensive patterns
Strategy: try-catch
Validate before calling
let exists: bool = sqlx::query_scalar(
"SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'currency')",
).fetch_one(pool).await?;
if !exists {
return Err(anyhow::anyhow!("'currency' table missing — run migrations"));
} Try / catch
match DatabaseQueries::load_currencies(&pool).await {
Err(e) if e.to_string().contains("error decoding") => {
return Err(anyhow::anyhow!(
"currency rows unreadable by this version — align writer/reader versions: {e}"
));
}
result => result?,
} Prevention
- Keep writer and reader application versions aligned so all stored enum values decode.
- Run migrations before loading currencies from a cache database.
- Verify DATABASE_URL targets the intended cache database.
- Classify failures from the inner sqlx error (missing relation vs decode error).
When it happens
Trigger: Calling `DatabaseQueries::load_currencies(pool)` when the connection fails, the `currency` table doesn't exist, or a CurrencyRow fails to decode (e.g. a newer enum variant in the DB that CurrencyTypePg in this version rejects).
Common situations: Version skew: currencies persisted by a newer Nautilus release, then read by an older binary at startup; fresh database without migrations; transient network errors during fetch.
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 insert into currency table: {e}
- Failed to load currency: {e}
- Failed to load general table: {e}
- Failed to load instrument with id {instrument_id},error is:
- Failed to load instrument closes: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/31a5490e5820be59.
Report an issue: GitHub.