{"record":{"id":"50c001ee58860f88","repo":"nautechsystems/nautilus_trader","slug":"failed-to-mark-execution-event-emitted-e","errorCode":null,"errorMessage":"Failed to mark execution {event} emitted: {e}","messagePattern":"Failed to mark execution (.+?) emitted: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":3899,"sourceCode":"        event: &str,\n    ) -> anyhow::Result<()> {\n        let statement = match event {\n            \"acknowledgement\" => {\n                \"UPDATE execution_intent SET acknowledgement_emitted = TRUE, updated_at = NOW() WHERE id = $1\"\n            }\n            \"fill\" => {\n                \"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\"\n            }\n            \"terminal\" => {\n                \"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\"\n            }\n            _ => anyhow::bail!(\"Unknown execution event marker {event}\"),\n        };\n        let result = sqlx::query(statement)\n            .bind(intent_id)\n            .execute(&self.pool)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to mark execution {event} emitted: {e}\"))?;\n        anyhow::ensure!(\n            result.rows_affected() == 1,\n            \"Execution intent {intent_id} cannot mark {event} emitted\"\n        );\n        Ok(())\n    }\n\n    /// Updates the status of a persisted execution transaction record.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the database operation fails.\n    pub async fn update_execution_transaction_status(\n        &self,\n        chain_id: u32,\n        transaction_hash: &str,\n        status: &str,\n    ) -> anyhow::Result<()> {","sourceCodeStart":3881,"sourceCodeEnd":3917,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/2114cf6f761429e0adb5ca9596fcd7b895b16011/crates/adapters/blockchain/src/cache/database.rs#L3881-L3917","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check: the event kind must be one the statements cover\nanyhow::ensure!(\n    matches!(event, \"acknowledgement\" | \"fill\" | \"terminal\"),\n    \"unknown execution event {event}\"\n);","typeGuard":"fn is_transient_db_error(err: &anyhow::Error) -> bool {\n    err.downcast_ref::<sqlx::Error>().map_or(false, |e| {\n        matches!(e, sqlx::Error::PoolTimedOut | sqlx::Error::PoolClosed | sqlx::Error::Io(_))\n            || e.as_database_error().and_then(|d| d.code()).map_or(false, |c| {\n                matches!(c.as_ref(), \"08000\" | \"08003\" | \"08006\" | \"57014\" | \"40001\" | \"40P01\")\n            })\n    })\n}","tryCatchPattern":"match db.mark_execution_event_emitted(intent_id, event).await {\n    Ok(()) => Ok(()),\n    Err(e) if is_transient_db_error(&e) => {\n        // the guard clauses make re-marking the same event idempotent, so retry hard:\n        // skipping it risks duplicate order-event emission after a restart\n        retry_with_backoff(e)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["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"],"tags":["rust","sqlx","postgres","blockchain","event-dispatch","transaction"],"backgroundTag":"database-update-failed","analyzedSha":"2114cf6f761429e0adb5ca9596fcd7b895b16011","analyzedAt":"2026-08-21T11:28:30.864Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}