{"record":{"id":"c7a5d944f505e21b","repo":"nautechsystems/nautilus_trader","slug":"active-execution-intent-intent-id-was-not-found","errorCode":null,"errorMessage":"Active execution intent {intent_id} was not found","messagePattern":"Active execution intent (.+?) was not found","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":3800,"sourceCode":"    pub async fn add_execution_replacement_hash(\n        &self,\n        intent_id: i64,\n        chain_id: u32,\n        transaction_hash: &str,\n    ) -> anyhow::Result<ExecutionTransactionHashRow> {\n        let chain_id_db = i32::try_from(chain_id)\n            .with_context(|| format!(\"Chain ID {chain_id} exceeds PostgreSQL INTEGER\"))?;\n        let mut transaction = self.pool.begin().await.map_err(|e| {\n            anyhow::anyhow!(\"Failed to start replacement transaction persistence: {e}\")\n        })?;\n        let current_status = sqlx::query_scalar::<_, String>(\n            \"SELECT status FROM execution_intent WHERE id = $1 AND active FOR UPDATE\",\n        )\n        .bind(intent_id)\n        .fetch_optional(&mut *transaction)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to lock active execution intent {intent_id}: {e}\"))?\n        .ok_or_else(|| anyhow::anyhow!(\"Active execution intent {intent_id} was not found\"))?;\n        anyhow::ensure!(\n            execution_transition_allowed(&current_status, TransactionStatus::Replaced),\n            \"Invalid execution transition for intent {intent_id}: {current_status} -> replaced\"\n        );\n\n        sqlx::query(\n            \"\n            UPDATE execution_transaction_hash\n            SET current = FALSE, status = 'replaced', updated_at = NOW()\n            WHERE intent_id = $1 AND current\n            \",\n        )\n        .bind(intent_id)\n        .execute(&mut *transaction)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to retire replaced execution hash: {e}\"))?;\n\n        let row = sqlx::query_as::<_, ExecutionTransactionHashRow>(","sourceCodeStart":3782,"sourceCodeEnd":3818,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/2114cf6f761429e0adb5ca9596fcd7b895b16011/crates/adapters/blockchain/src/cache/database.rs#L3782-L3818","documentation":"Raised in add_execution_replacement_hash (database.rs:3800) when the locking SELECT ... WHERE id = $1 AND active returns no row: the intent either does not exist or is no longer active. The active flag is flipped to false by terminal processing (record_execution_status sets active=false once finalized/reverted and both event markers are emitted, and mark_execution_event_emitted deactivates on terminal markers), so 'not found' here usually means the intent already completed.","triggerScenarios":"Recording a replacement hash after the intent was finalized and its fill/terminal event was marked emitted (active=false); passing an intent_id that was never created or belongs to another database; the intent deactivated by a concurrent transaction that committed first.","commonSituations":"A reorg/replacement race where the finality watcher wins and the replacement watcher arrives late; replaying queued replacement events after a restart against an intent that finished meanwhile; mixed-up intent ids when several wallets trade the same pool.","solutions":["Check the intent's actual state: SELECT status, active, fill_emitted, terminal_emitted FROM execution_intent WHERE id = $1","If the intent is finalized/reverted, treat the replacement observation as stale and skip it (the transaction never started mutating anything)","If the id simply does not exist, fix the caller that produced it (re-resolve via get_active_execution_intent instead of caching ids)","If active=false but status is non-terminal, investigate what deactivated the row before overriding anything"],"exampleFix":"// before: a late replacement observation crashes the watcher\nlet row = db.add_execution_replacement_hash(intent_id, chain_id, &hash).await?;\n\n// after: treat 'no active intent' as a benign stale event\nmatch db.add_execution_replacement_hash(intent_id, chain_id, &hash).await {\n    Ok(row) => Ok(Some(row)),\n    Err(e) if e.to_string().contains(\"was not found\") => Ok(None), // intent already completed\n    Err(e) => Err(e),\n}","handlingStrategy":"validation","validationCode":"// pre-check: is the intent still active before recording a late replacement?\nlet row = sqlx::query_as::<_, (bool,)>(\"SELECT active FROM execution_intent WHERE id = $1\")\n    .bind(intent_id)\n    .fetch_optional(&pool)\n    .await?;\nif !row.is_some_and(|(active,)| active) {\n    // intent absent or completed: skip the stale replacement event\n    return Ok(None);\n}","typeGuard":null,"tryCatchPattern":"match db.add_execution_replacement_hash(intent_id, chain_id, &hash).await {\n    Ok(row) => Ok(Some(row)),\n    Err(e) if e.to_string().contains(\"was not found\") => Ok(None), // stale: already terminal/inactive\n    Err(e) => Err(e),\n}","preventionTips":["In replacement/finality races, tolerate the loser's write failing with not-found instead of crashing the watcher","Do not cache intent state across restarts; re-read active status when replaying queued events","Design event consumers so out-of-order delivery is a skip, not an error path"],"tags":["rust","sqlx","postgres","blockchain","not-found","lifecycle","stale-event"],"backgroundTag":"database-row-not-found","analyzedSha":"2114cf6f761429e0adb5ca9596fcd7b895b16011","analyzedAt":"2026-08-21T11:28:30.864Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}