{"record":{"id":"0e4486cf81afcb16","repo":"nautechsystems/nautilus_trader","slug":"failed-to-lock-execution-intent-intent-id-e","errorCode":null,"errorMessage":"Failed to lock execution intent {intent_id}: {e}","messagePattern":"Failed to lock execution intent (.+?): (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":6658,"sourceCode":"            let marker = sqlx::query_scalar::<_, bool>(\n                \"SELECT EXISTS (SELECT 1 FROM execution_schema_version WHERE component = $1)\",\n            )\n            .bind(EXECUTION_PAYLOAD_COMPONENT)\n            .fetch_one(&mut *transaction)\n            .await\n            .context(\"failed to inspect execution payload marker\")?;\n            anyhow::ensure!(\n                !marker,\n                \"Plaintext signed transaction persistence is disabled after payload activation\"\n            );\n        }\n        let current_status = sqlx::query_scalar::<_, String>(\n            \"SELECT status FROM execution_intent WHERE id = $1 FOR UPDATE\",\n        )\n        .bind(intent_id)\n        .fetch_optional(&mut *transaction)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to lock execution intent {intent_id}: {e}\"))?\n        .ok_or_else(|| anyhow::anyhow!(\"Execution intent {intent_id} was not found\"))?;\n        anyhow::ensure!(\n            current_status == TransactionStatus::Prepared.as_str()\n                || current_status == TransactionStatus::Signed.as_str(),\n            \"Execution intent {intent_id} is {current_status}, not prepared for signing\"\n        );\n\n        let row = sqlx::query_as::<_, ExecutionTransactionHashRow>(\n            \"\n            INSERT INTO execution_transaction_hash (\n                intent_id, chain_id, transaction_hash, payload_expected,\n                raw_transaction, sealed_transaction, status\n            )\n            SELECT id, chain_id, $3, TRUE, $4, $5, 'signed'\n            FROM execution_intent\n            WHERE id = $1 AND chain_id = $2 AND nonce IS NOT NULL\n            ON CONFLICT (chain_id, transaction_hash) DO UPDATE\n            SET transaction_hash = EXCLUDED.transaction_hash","sourceCodeStart":6640,"sourceCodeEnd":6676,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L6640-L6676","documentation":"The FOR UPDATE row lock on the execution_intent row failed at the database level. The library wraps the sqlx error so the caller knows it could not acquire a lock on the intent row, which is required to safely advance the intent's status during signing persistence.","triggerScenarios":"The SELECT ... FOR UPDATE on execution_intent WHERE id = $1 returned a database error: connection loss mid-query, statement timeout while another transaction holds the row lock, serialization/deadlock abort, or the row being blocked by a long-running transaction.","commonSituations":"Two workers persisting signed transactions for the same intent concurrently with long outer transactions; a stuck transaction holding the lock until lock_timeout fires; network blip to PostgreSQL during the statement.","solutions":["Retry the operation after a short backoff — the conflicting transaction usually commits or rolls back quickly.","Check pg_locks / pg_stat_activity for the transaction blocking the execution_intent row and resolve the long-running holder.","Increase statement/lock timeout if contention is expected, or shorten surrounding transactions.","Verify database connectivity and re-establish the pool if the error indicates connection loss."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-check contention\nlet blocked = sqlx::query_scalar::<_, i64>(\"SELECT count(*) FROM pg_locks WHERE relation = 'execution_intent'::regclass AND NOT granted\").fetch_one(&pool).await?;\nif blocked > 0 { tokio::time::sleep(Duration::from_millis(200)).await; }","typeGuard":null,"tryCatchPattern":"let row = retry(3, backoff(100).factor(2.0), || async {\n    db.add_execution_transaction(intent_id, chain_id, hash, sealed).await\n}).await.context(\"failed to lock execution intent after retries\")?;","preventionTips":["Keep transactions that hold the FOR UPDATE lock short","Set explicit lock_timeout and retry transient lock failures with jittered backoff","Use a single owner (queue/leader) per intent to avoid lock contention","Monitor pg_locks for waiting transactions on execution_intent"],"tags":["database","locking","concurrency","postgresql"],"backgroundTag":"database-query-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}