nautechsystems/nautilus_trader · error · anyhow::Error
Failed to mark execution {event} emitted: {e}
Error message
Failed to mark execution {event} emitted: {e} What it means
Wrapped sqlx error from the UPDATE statement executed by mark_execution_event_emitted (database.rs:3885-3899). The event parameter selects one of two statements: 'fill' sets fill_emitted (and deactivates when status = 'finalized'), 'terminal' sets terminal_emitted (and deactivates when status is 'finalized' or 'reverted'); both guard against the opposing marker in the WHERE clause. This error means the chosen UPDATE failed at the database level; an unknown event string is a separate bail, and a zero-row match is error 98.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:3899
event: &str,
) -> anyhow::Result<()> {
let statement = match event {
"acknowledgement" => {
"UPDATE execution_intent SET acknowledgement_emitted = TRUE, updated_at = NOW() WHERE id = $1"
}
"fill" => {
"UPDATE execution_intent SET fill_emitted = TRUE, active = CASE WHEN status = 'finalized' THEN FALSE ELSE active END, updated_at = NOW() WHERE id = $1 AND NOT terminal_emitted"
}
"terminal" => {
"UPDATE execution_intent SET terminal_emitted = TRUE, active = CASE WHEN status IN ('finalized', 'reverted') THEN FALSE ELSE active END, updated_at = NOW() WHERE id = $1 AND NOT fill_emitted"
}
_ => anyhow::bail!("Unknown execution event marker {event}"),
};
let result = sqlx::query(statement)
.bind(intent_id)
.execute(&self.pool)
.await
.map_err(|e| anyhow::anyhow!("Failed to mark execution {event} emitted: {e}"))?;
anyhow::ensure!(
result.rows_affected() == 1,
"Execution intent {intent_id} cannot mark {event} emitted"
);
Ok(())
}
/// Updates the status of a persisted execution transaction record.
///
/// # Errors
///
/// Returns an error if the database operation fails.
pub async fn update_execution_transaction_status(
&self,
chain_id: u32,
transaction_hash: &str,
status: &str,
) -> anyhow::Result<()> {View on GitHub (pinned to 2114cf6f76)
Solutions
- Downcast to sqlx::Error to classify the cause (connectivity, constraint, or schema)
- Apply migrations so execution_intent has fill_emitted, terminal_emitted, active, and updated_at
- Retry the marking on transient classes - the guard clauses make re-marking the same event idempotent (rows still match)
- If the dispatcher already emitted the event upstream, prioritize retrying the marker so events are not re-emitted after a restart
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check: the event kind must be one the statements cover
anyhow::ensure!(
matches!(event, "acknowledgement" | "fill" | "terminal"),
"unknown execution event {event}"
); Type guard
fn is_transient_db_error(err: &anyhow::Error) -> bool {
err.downcast_ref::<sqlx::Error>().map_or(false, |e| {
matches!(e, sqlx::Error::PoolTimedOut | sqlx::Error::PoolClosed | sqlx::Error::Io(_))
|| e.as_database_error().and_then(|d| d.code()).map_or(false, |c| {
matches!(c.as_ref(), "08000" | "08003" | "08006" | "57014" | "40001" | "40P01")
})
})
} Try / catch
match db.mark_execution_event_emitted(intent_id, event).await {
Ok(()) => Ok(()),
Err(e) if is_transient_db_error(&e) => {
// the guard clauses make re-marking the same event idempotent, so retry hard:
// skipping it risks duplicate order-event emission after a restart
retry_with_backoff(e)
}
Err(e) => Err(e),
} Prevention
- Mark the event emitted immediately after successful dispatch; a crash between dispatch and marking causes duplicate emission
- Keep marker columns (fill_emitted, terminal_emitted) in every migration snapshot
- Restrict event strings to acknowledgement/fill/terminal at the call site instead of relying on the bail
When it happens
Trigger: Connection loss or pool timeout while marking the event; a CHECK constraint rejecting an unexpected value; schema drift where fill_emitted/terminal_emitted/active/updated_at columns are missing; Postgres restart between acquiring the pooled connection and executing the UPDATE.
Common situations: Event dispatch loop hitting a Postgres blip after emitting an order event but before marking it; database created before event-marker columns were added by migrations; concurrent marking from multiple dispatcher tasks.
Related errors
- Failed to update execution hash {transaction_hash}: {e}
- Failed to update execution intent {intent_id}: {e}
- Failed to record execution transition: {e}
- Failed to start replacement transaction persistence: {e}
- Failed to retire replaced execution hash: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21).
Data as JSON: /api/errors/50c001ee58860f88.
Report an issue: GitHub.