{"record":{"id":"d800d4145e4e33a3","repo":"nautechsystems/nautilus_trader","slug":"execution-payload-rollback-state-is-missing","errorCode":null,"errorMessage":"Execution payload rollback state is missing","messagePattern":"Execution payload rollback state is missing","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":5630,"sourceCode":"    async fn rollback_execution_payload_batch(\n        &self,\n        keys: &PayloadKeySet,\n        batch_size: i64,\n    ) -> anyhow::Result<bool> {\n        let mut transaction = self\n            .pool\n            .begin()\n            .await\n            .context(\"failed to start execution payload rollback batch\")?;\n        lock_execution_payload_operation(&mut transaction).await?;\n        let state_row = sqlx::query(\n            \"SELECT deployment_id, protocol_version, operation, active_key_id \\\n             FROM execution_payload_state WHERE component = 'signed_transactions' FOR UPDATE\",\n        )\n        .fetch_optional(&mut *transaction)\n        .await\n        .context(\"failed to lock execution payload rollback state\")?\n        .ok_or_else(|| anyhow::anyhow!(\"Execution payload rollback state is missing\"))?;\n        let state = execution_payload_state_from_row(&state_row)?;\n        validate_execution_payload_state(&state, keys)?;\n        anyhow::ensure!(\n            state.operation == \"rollback\",\n            \"Execution payload storage is not rolling back\"\n        );\n        let rows = sqlx::query_as::<_, ExecutionTransactionHashRow>(\n            \"\n            SELECT\n                id, intent_id, chain_id, transaction_hash, payload_expected,\n                raw_transaction, sealed_transaction, status, block_number, block_hash,\n                receipt_success, gas_used, effective_gas_price, current\n            FROM execution_transaction_hash\n            WHERE payload_expected AND sealed_transaction IS NOT NULL\n            ORDER BY id\n            LIMIT $1\n            FOR UPDATE\n            \",","sourceCodeStart":5612,"sourceCodeEnd":5648,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L5612-L5648","documentation":"The finalize/complete phase of an execution payload rollback locks execution_payload_state for component 'signed_transactions' and requires it to exist with operation == 'rollback'. This error is thrown when the state row is absent, meaning a rollback is not in progress so there is no rollback state to complete.","triggerScenarios":"Calling the rollback-finalization routine without having first called begin_execution_payload_rollback; the state row was deleted after a prior rollback completed; running finalize against a different database than the one where the rollback began.","commonSituations":"Re-running a rollback completion after it already finished and cleaned up state; a crashed/interrupted deployment where the state row was manually removed; mixing environments (staging DB connection used to finalize a production rollback).","solutions":["Start the rollback first (begin_execution_payload_rollback via rollback_execution_payload_storage) before invoking the finalization step","If the rollback already completed, skip finalization — check updated_at/operation history to confirm","Confirm the finalization call targets the same database/schema where the rollback was started"],"exampleFix":"// before\ncomplete_execution_payload_rollback(&keys).await?;\n// after: ensure rollback is in progress first\nlet state = fetch_execution_payload_state(&db).await?;\nif state.map(|s| s.operation == \"rollback\").unwrap_or(false) {\n    complete_execution_payload_rollback(&keys).await?;\n}","handlingStrategy":"validation","validationCode":"let state = sqlx::query(\n    \"SELECT operation FROM execution_payload_state WHERE component = 'signed_transactions'\")\n    .fetch_optional(&db).await?;\nlet in_rollback = state.map(|s| s.operation == \"rollback\").unwrap_or(false);\nif !in_rollback { /* skip or start rollback first */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pair begin and finalize phases of the rollback in one operator runbook","Make finalize idempotent/skippable when state is absent","Log the rollback state transition so interrupted runs are visible"],"tags":["rust","database","state","rollback"],"backgroundTag":"resource-not-found","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"}