{"record":{"id":"88a08e851920d99e","repo":"nautechsystems/nautilus_trader","slug":"failed-to-commit-replacement-transaction-e","errorCode":null,"errorMessage":"Failed to commit replacement transaction: {e}","messagePattern":"Failed to commit replacement transaction: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":3868,"sourceCode":"            \"\n            INSERT INTO execution_transaction_transition (\n                intent_id, transaction_hash_id, transition_key, from_status, to_status\n            ) VALUES ($1, $2, $3, $4, 'replaced')\n            ON CONFLICT (intent_id, transition_key) DO NOTHING\n            \",\n        )\n        .bind(intent_id)\n        .bind(row.id)\n        .bind(format!(\"replaced:{transaction_hash}\"))\n        .bind(current_status)\n        .execute(&mut *transaction)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to record replacement transition: {e}\"))?;\n\n        transaction\n            .commit()\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to commit replacement transaction: {e}\"))?;\n        Ok(row)\n    }\n\n    /// Marks one order event as emitted after dispatch.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the event kind is unknown, the intent is absent, the opposing\n    /// terminal marker is already set, or persistence fails.\n    pub async fn mark_execution_event_emitted(\n        &self,\n        intent_id: i64,\n        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            }","sourceCodeStart":3850,"sourceCodeEnd":3886,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/2114cf6f761429e0adb5ca9596fcd7b895b16011/crates/adapters/blockchain/src/cache/database.rs#L3850-L3886","documentation":"Wrapped sqlx error when transaction.commit() fails at the end of add_execution_replacement_hash (database.rs:3865-3869). All statements (lock, retire, upsert, status update, transition insert) already executed, so the durable outcome is ambiguous: the replacement may or may not have been persisted. The idempotency key 'replaced:{transaction_hash}' in the transition table makes a plain replay of the same call the safe resolution.","triggerScenarios":"Connection dying at commit; Postgres restart or failover; serialization failure surfacing at commit; pool returning a broken connection for the commit round-trip.","commonSituations":"Unstable network between the trading host and Postgres; failover events during bursts of replacement/reorg processing; connection reaper killing sessions held open by slow commit paths.","solutions":["Retry add_execution_replacement_hash with identical arguments; ON CONFLICT clauses make the replay converge","If repeated commits fail, verify connection stability (keepalives, PgBouncer pooling mode, Postgres uptime)","Check the transition table afterward if you must know whether the first attempt committed: SELECT 1 FROM execution_transaction_transition WHERE intent_id = $1 AND transition_key = 'replaced:' || $2","Keep the transaction short so the commit window is minimal"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"fn is_commit_ambiguity(err: &anyhow::Error) -> bool {\n    matches!(err.downcast_ref::<sqlx::Error>(), Some(sqlx::Error::Io(_)) | None)\n}","tryCatchPattern":"match db.add_execution_replacement_hash(intent_id, chain_id, &hash).await {\n    Ok(row) => Ok(row),\n    Err(e) if is_commit_ambiguity(&e) => {\n        // outcome unknown: replay; 'replaced:{hash}' transition key dedupes if it committed\n        db.add_execution_replacement_hash(intent_id, chain_id, &hash).await\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Rely on the transition_key idempotency design: replays after commit ambiguity are the intended recovery","Minimize the commit window by keeping transactions short and free of external awaits","Investigate repeated commit failures as connection-layer instability, not application logic"],"tags":["rust","sqlx","postgres","blockchain","commit","idempotency","replacement"],"backgroundTag":"db-transaction-commit-failed","analyzedSha":"2114cf6f761429e0adb5ca9596fcd7b895b16011","analyzedAt":"2026-08-21T11:28:30.864Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}