{"record":{"id":"d286642ca509fa7a","repo":"nautechsystems/nautilus_trader","slug":"execution-intent-intent-id-cannot-mark-event-e","errorCode":null,"errorMessage":"Execution intent {intent_id} cannot mark {event} emitted","messagePattern":"Execution intent (.+?) cannot mark (.+?) emitted","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":3900,"sourceCode":"    ) -> 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<()> {\n        let result = sqlx::query(","sourceCodeStart":3882,"sourceCodeEnd":3918,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/2114cf6f761429e0adb5ca9596fcd7b895b16011/crates/adapters/blockchain/src/cache/database.rs#L3882-L3918","documentation":"Guard in mark_execution_event_emitted (database.rs:3900-3903): the selected UPDATE affected zero rows. The WHERE clauses make fill and terminal markers mutually exclusive per intent - 'fill' requires NOT terminal_emitted and 'terminal' requires NOT fill_emitted - so re-marking the SAME event twice still matches (rows_affected = 1), and this error fires only when the intent row is absent or the OPPOSING marker is already set. It is a by-design duplicate/ordering suppression, not an infrastructure fault.","triggerScenarios":"Calling mark_execution_event_emitted(intent_id, \"fill\") after \"terminal\" was already marked for that intent (or vice versa); passing an intent_id that does not exist or was archived. The terminal path also only deactivates the intent when status is 'finalized'/'reverted', so wrong-order marking leaves the intent active and this error surfaces.","commonSituations":"Dispatcher logic that emits both a fill event and a terminal event for the same intent (the schema allows exactly one); replaying recorded events after a restart in a different order than originally dispatched; a stale in-flight dispatch task marking an event after a newer task marked the opposite kind.","solutions":["Inspect the current markers: SELECT fill_emitted, terminal_emitted, status FROM execution_intent WHERE id = $1","If the opposing marker is set, treat this as duplicate suppression and skip - the intent already had its single event marker recorded","Fix dispatcher logic that tries to mark both fill and terminal for one intent; the schema's mutual exclusion is intentional","If the intent row is absent, verify the intent_id source (it should come from the row that created the event)"],"exampleFix":"// before: marking both events for one intent fails on the second call\ndb.mark_execution_event_emitted(intent_id, \"fill\").await?;\ndb.mark_execution_event_emitted(intent_id, \"terminal\").await?; // Err: cannot mark terminal emitted\n\n// after: choose exactly one marker per intent, and skip if the opposing one is set\nlet (fill, terminal) = sqlx::query_as::<_, (bool, bool)>(\n    \"SELECT fill_emitted, terminal_emitted FROM execution_intent WHERE id = $1\",\n).bind(intent_id).fetch_one(&pool).await?;\nif !terminal { db.mark_execution_event_emitted(intent_id, \"fill\").await?; }","handlingStrategy":"validation","validationCode":"// pre-check: fill and terminal markers are mutually exclusive per intent\nlet (fill_emitted, terminal_emitted) = sqlx::query_as::<_, (bool, bool)>(\n    \"SELECT fill_emitted, terminal_emitted FROM execution_intent WHERE id = $1\",\n)\n.bind(intent_id)\n.fetch_one(&pool)\n.await?;\nlet may_mark = match event {\n    \"fill\" => !terminal_emitted,\n    \"terminal\" => !fill_emitted,\n    _ => false,\n};\nif may_mark {\n    db.mark_execution_event_emitted(intent_id, event).await?;\n}","typeGuard":null,"tryCatchPattern":"match db.mark_execution_event_emitted(intent_id, event).await {\n    Ok(()) => Ok(()),\n    Err(e) if e.to_string().contains(\"cannot mark\") => Ok(()), // duplicate suppression: opposing marker already set\n    Err(e) => Err(e),\n}","preventionTips":["Emit at most one of fill/terminal per intent; the schema deliberately allows only one marker","Make dispatch deterministic (single dispatcher per intent) so markers cannot race","Treat this guard firing as a signal of dispatcher logic bugs, not as a transient fault to retry","Verify intent_id provenance when it fires with a missing row"],"tags":["rust","sqlx","postgres","blockchain","event-dispatch","idempotency","state-guard"],"backgroundTag":"invalid-state-transition","analyzedSha":"2114cf6f761429e0adb5ca9596fcd7b895b16011","analyzedAt":"2026-08-21T11:28:30.864Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}