{"record":{"id":"f0880570e4ea526c","repo":"nautechsystems/nautilus_trader","slug":"signed-transaction-transaction-hash-conflicts-wi","errorCode":null,"errorMessage":"Signed transaction {transaction_hash} conflicts with its persisted identity","messagePattern":"Signed transaction (.+?) conflicts with its persisted identity","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":6709,"sourceCode":"            RETURNING\n                id, intent_id, chain_id, transaction_hash, payload_expected,\n                raw_transaction, sealed_transaction, status,\n                block_number, block_hash, receipt_success, gas_used,\n                effective_gas_price, current\n            \",\n        )\n        .bind(intent_id)\n        .bind(chain_id_db)\n        .bind(transaction_hash)\n        .bind(raw_transaction)\n        .bind(sealed_transaction)\n        .fetch_optional(&mut *transaction)\n        .await\n        .map_err(|e| {\n            anyhow::anyhow!(\"Failed to persist signed transaction {transaction_hash}: {e}\")\n        })?\n        .ok_or_else(|| {\n            anyhow::anyhow!(\n                \"Signed transaction {transaction_hash} conflicts with its persisted identity\"\n            )\n        })?;\n\n        sqlx::query(\n            \"UPDATE execution_intent SET status = 'signed', updated_at = NOW() WHERE id = $1\",\n        )\n        .bind(intent_id)\n        .execute(&mut *transaction)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to mark execution intent signed: {e}\"))?;\n        sqlx::query(\n            \"\n            INSERT INTO execution_transaction_transition (\n                intent_id, transaction_hash_id, transition_key, from_status, to_status\n            ) VALUES ($1, $2, $3, $4, 'signed')\n            ON CONFLICT (intent_id, transition_key) DO NOTHING\n            \",","sourceCodeStart":6691,"sourceCodeEnd":6727,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L6691-L6727","documentation":"The upsert's conflict-update WHERE clause matched no row, so RETURNING produced nothing: an existing execution_transaction_hash row for (chain_id, transaction_hash) exists but belongs to a different intent, lacks payload_expected, or stores a different payload than the one being persisted. The library rejects this identity conflict rather than overwriting the persisted record.","triggerScenarios":"Persisting a signed transaction whose (chain_id, transaction_hash) already exists under another intent_id (reused nonce producing the same hash), or re-persisting the same hash with different raw/sealed bytes than stored, or the existing row has payload_expected = FALSE.","commonSituations":"Duplicate nonce assignment causing two intents to produce the identical transaction hash; a corrupted or partially-migrated row; replaying a signing job against a database where the hash row was created by a different intent; mixed deployments producing different sealed bytes for the same transaction.","solutions":["Query the existing row: SELECT intent_id, payload_expected FROM execution_transaction_hash WHERE chain_id=$1 AND transaction_hash=$2 and reconcile which intent actually owns the hash.","Fix nonce allocation so two intents never produce the same transaction hash; re-issue the losing intent with a new nonce.","Do not retry with the same payload expecting success — the conflict is deterministic; investigate the differing payload bytes instead.","If the row was created by an aborted/incorrect flow, correct it through the supported recovery path, never by direct UPDATE."],"exampleFix":"// before\nlet existing: Option<_> = sqlx::query_scalar(\n    \"SELECT intent_id FROM execution_transaction_hash WHERE chain_id=$1 AND transaction_hash=$2\")\n    .bind(chain_id).bind(hash).fetch_optional(&pool).await?;\n// after\nif let Some(owner) = existing {\n    anyhow::ensure!(owner == intent_id, \"hash {hash} owned by intent {owner}; allocate a fresh nonce\");\n}","handlingStrategy":"validation","validationCode":"let owner: Option<i64> = sqlx::query_scalar(\n    \"SELECT intent_id FROM execution_transaction_hash WHERE chain_id=$1 AND transaction_hash=$2\")\n    .bind(chain_id as i32).bind(transaction_hash).fetch_optional(&pool).await?;\nanyhow::ensure!(owner.map_or(true, |o| o == intent_id), \"hash {transaction_hash} already persisted under intent {owner:?}\");","typeGuard":null,"tryCatchPattern":"match db.add_execution_transaction(intent_id, chain_id, hash, sealed).await {\n    Err(e) if e.to_string().contains(\"conflicts with its persisted identity\") => {\n        // deterministic conflict: reconcile ownership / reissue intent, do not blind-retry\n        alert_identity_conflict(intent_id, hash);\n    }\n    r => r?,\n}","preventionTips":["Guarantee unique nonce allocation per chain so hashes never collide across intents","Look up existing (chain_id, transaction_hash) rows before signing","Never reuse signed payloads across intents or environments","Treat this error as an integrity alarm, not a transient failure"],"tags":["database","conflict","integrity","transactions"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}