nautechsystems/nautilus_trader · error
Failed to insert into order_event table: {e}
Error message
Failed to insert into order_event table: {e} What it means
Wraps the sqlx failure of the final INSERT into the `order_event` table inside `add_order_event`, just before commit. The transaction is aborted implicitly and the caller receives this anyhow-wrapped error. Common causes are constraint violations (PK/duplicate client_order_id+kind), column type mismatches, or connectivity loss.
Source
Thrown at crates/infrastructure/src/sql/queries.rs:760
.bind(order_event.account_id().map(|x| x.to_string()))
.bind(order_event.position_id().map(|x| x.to_string()))
.bind(order_event.commission().map(|x| x.to_string()))
.bind(order_event.ts_event().to_string())
.bind(order_event.ts_init().to_string())
.bind(order_event.activation_price().map(|x| x.to_string()))
.bind(exec_algorithm_params)
.bind(order_event.tags().map(|x| x.iter().map(ToString::to_string).collect::<Vec<String>>()))
.bind(order_event.released_price().map(|x| x.to_string()))
.bind(order_event.protection_price().map(|x| x.to_string()))
.bind(order_event.due_post_only())
.bind(order_event.correction_id().map(|x| x.to_string()))
.bind(order_event.is_reopened())
.bind(info)
.bind(order_event.causation_id().map(|x| x.to_string()))
.execute(&mut *transaction)
.await
.map(|_| ())
.map_err(|e| anyhow::anyhow!("Failed to insert into order_event table: {e}"))?;
transaction
.commit()
.await
.map_err(|e| anyhow::anyhow!("Failed to commit transaction: {e}"))
}
/// Loads all order events for a `client_order_id` via the provided `pool`.
///
/// # Errors
///
/// Returns an error if the SQL SELECT or deserialization fails.
pub async fn load_order_events(
pool: &PgPool,
client_order_id: &ClientOrderId,
) -> anyhow::Result<Vec<OrderEventAny>> {
sqlx::query_as::<_, OrderEventAnyRow>(r#"SELECT * FROM "order_event" event WHERE event.client_order_id = $1 ORDER BY created_at ASC"#)
.bind(client_order_id.to_string())
.fetch_all(pool)View on GitHub (pinned to 18893faf8b)
Solutions
- Check `{e}` for a unique/PK violation and deduplicate before inserting (use the existence checks).
- Run migrations so the `order_event` schema matches the Rust INSERT column list.
- Verify JSON columns (`exec_algorithm_params`, `info`) accept the serialized values.
- Retry `add_order_event`; the transaction ensures no partial rows remain.
Example fix
// before
add_order_event(&mut tx, &event, None).await?;
// after
if !check_if_order_initialized_exists(&pool, event.client_order_id()).await? {
add_order_event(&mut tx, &event, None).await?;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Avoid duplicate inserts by checking first
let exists = sqlx::query(
r#"SELECT EXISTS(SELECT 1 FROM "order_event" WHERE client_order_id = $1 AND kind = $2)"#)
.bind(event.client_order_id().to_string())
.bind(event.kind().to_string())
.fetch_one(pool).await
.map(|row| row.get::<bool, _>(0))
.unwrap_or(false);
if exists { return Ok(()); } Type guard
fn is_unique_violation(e: &anyhow::Error) -> bool {
let s = e.to_string();
s.contains("duplicate key") || s.contains("23505")
} Try / catch
match add_order_event(&mut tx, &event, client_id).await {
Ok(()) => {}
Err(e) if is_unique_violation(&e) => { /* idempotent: already inserted */ }
Err(e) => return Err(e),
} Prevention
- Deduplicate events before persisting (check existence by client_order_id + kind).
- Run migrations so the column list matches the Rust INSERT.
- Bound payload sizes (reason/info) to column limits.
- Enable pool reconnects for long reconciliation runs.
When it happens
Trigger: Calling `add_order_event` when the order_event INSERT violates a primary key/unique constraint (re-adding the same event), a column value exceeds its type/length, or the DB connection drops during the insert.
Common situations: Replaying the same event twice during reconciliation; schema drift between the Rust column list and the migrated table; oversized reason/info payloads; DB failover mid-transaction.
Related errors
- 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}
- Failed to insert into dex table: {e}
- Failed to insert into pool table: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4579ccd18e17adc9.
Report an issue: GitHub.