nautechsystems/nautilus_trader · error
Failed to insert into trade table: {e}
Error message
Failed to insert into trade table: {e} What it means
This error wraps any sqlx failure from the INSERT INTO `trade` statement in `add_trade`. The library converts the raw database error into a message naming the operation. It means the TradeTick row was not persisted.
Source
Thrown at crates/infrastructure/src/sql/queries.rs:1263
$1, $2, $3, $4::aggressor_side, $5, $6, $7, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP
)
ON CONFLICT (id)
DO UPDATE
SET
instrument_id = $1, price = $2, quantity = $3, aggressor_side = $4, venue_trade_id = $5,
ts_event = $6, ts_init = $7, updated_at = CURRENT_TIMESTAMP
"#)
.bind(trade.instrument_id.to_string())
.bind(trade.price.to_string())
.bind(trade.size.to_string())
.bind(AggressorSidePg(trade.aggressor_side))
.bind(trade.trade_id.to_string())
.bind(trade.ts_event.to_string())
.bind(trade.ts_init.to_string())
.execute(pool)
.await
.map(|_| ())
.map_err(|e| anyhow::anyhow!("Failed to insert into trade table: {e}"))
}
/// Loads all `TradeTick` entries for `instrument_id` via the provided `pool`.
///
/// # Errors
///
/// Returns an error if the SQL SELECT or deserialization fails.
pub async fn load_trades(
pool: &PgPool,
instrument_id: &InstrumentId,
) -> anyhow::Result<Vec<TradeTick>> {
sqlx::query_as::<_, TradeTickRow>(
r#"SELECT * FROM "trade" WHERE instrument_id = $1 ORDER BY ts_event ASC"#,
)
.bind(instrument_id.to_string())
.fetch_all(pool)
.await
.map(|rows| rows.into_iter().map(|row| row.0).collect())View on GitHub (pinned to 18893faf8b)
Solutions
- Run migrations so the `trade` table and its enum types exist
- Check the wrapped sqlx error for constraint/type issues (column mismatch, invalid enum label) and align the schema or data
- Verify pool connectivity before batch inserts
- Use a transaction so failed trade inserts can be retried as a batch
Defensive patterns
Strategy: try-catch
Validate before calling
sqlx::query("SELECT 1 FROM trade LIMIT 1").fetch_optional(pool).await.map_err(|e| anyhow::anyhow!("trade table check: {e}"))?; Try / catch
if let Err(e) = add_trade(&pool, &trade).await {
tracing::error!("trade insert failed: {e:#}");
return Err(e.into());
} Prevention
- Ensure migrations create the trade table and enum types before writes
- Keep schema in sync with the library version
- Batch inserts inside a transaction for atomicity
When it happens
Trigger: Calling `add_trade(pool, &trade)` when the `trade` table does not exist, a column type/constraint fails (e.g. instrument_id or enum casting), the connection drops mid-insert, or the pool is closed.
Common situations: Migrations not run in a new environment; schema drift after upgrading (missing columns); enum values not representable in the Postgres enum types; DB credentials or network failures.
Related errors
- Failed to insert into quote table: {e}
- Error executing statement {sql_statement} with error: {e:?}
- Failed to insert into block table: {e}
- Failed to batch insert into block table: {e}
- Failed to batch insert into pool_event_block table: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9088214f8a6479a1.
Report an issue: GitHub.