{"record":{"id":"4839d55b839a63b8","repo":"nautechsystems/nautilus_trader","slug":"intent-cannot-make-the-verified-finality-transitio","errorCode":null,"errorMessage":"Intent cannot make the verified finality transition","messagePattern":"Intent cannot make the verified finality transition","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":7058,"sourceCode":"        }\n\n        let (current_status, intent_nonce, fill_emitted, terminal_emitted) =\n            sqlx::query_as::<_, (String, Option<i64>, bool, bool)>(\n                \"\n                SELECT status, nonce, fill_emitted, terminal_emitted\n                FROM execution_intent\n                WHERE id = $1 AND chain_id = $2 AND wallet_address = $3 AND active\n                FOR UPDATE\n                \",\n            )\n            .bind(finality.intent_id)\n            .bind(chain_id)\n            .bind(finality.wallet_address)\n            .fetch_optional(&mut *transaction)\n            .await\n            .map_err(|e| anyhow::anyhow!(\"Failed to lock intent for verified finality: {e}\"))?\n            .ok_or_else(|| anyhow::anyhow!(\"Active finality intent was not found\"))?;\n        anyhow::ensure!(\n            intent_nonce == Some(nonce)\n                && execution_transition_allowed(&current_status, finality.status),\n            \"Intent cannot make the verified finality transition\"\n        );\n\n        for (index, decision) in finality.decisions.iter().enumerate() {\n            let height_start = decision\n                .height_start\n                .map(i64::try_from)\n                .transpose()\n                .context(\"Verification height exceeds PostgreSQL BIGINT\")?;\n            let height_end = decision\n                .height_end\n                .map(i64::try_from)\n                .transpose()\n                .context(\"Verification height exceeds PostgreSQL BIGINT\")?;\n            let transition_key = format!(\n                \"finality:{}:{}:{index}\",","sourceCodeStart":7040,"sourceCodeEnd":7076,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L7040-L7076","documentation":"A state-machine guard: after locking the intent, the code ensure()s that the stored nonce matches the finality nonce and that `execution_transition_allowed(&current_status, finality.status)` permits the requested transition. Either the nonce is stale/wrong or the intent is in a status from which the target verified-finality status is not reachable. This prevents duplicate, out-of-order, or illegal finality transitions.","triggerScenarios":"Applying the same finality event twice (idempotency guard hit); finality arriving after the intent already moved to a terminal status; a nonce mismatch from replaying an older finality message; a code/config change that reordered statuses so the transition is no longer in the allowed map.","commonSituations":"At-least-once delivery from the event source re-delivering a processed finality event; two workers processing finality concurrently where the second sees an already-transitioned status; upgrading the adapter while historical events with old nonces are still in flight; mismatched nonce derivation between the intent creator and the finality verifier.","solutions":["Log current_status, finality.status, intent_nonce and expected nonce to see which condition failed","If the event was already applied, treat it as a duplicate and skip (the transition already happened)","Re-derive the nonce on the finality message and confirm it matches the intent's stored nonce","Check execution_transition_allowed's transition table covers the observed current→target status pair","Ensure single-writer ordering for finality events per intent (or make application idempotent upstream)"],"exampleFix":"// before\nanyhow::ensure!(\n    intent_nonce == Some(nonce)\n        && execution_transition_allowed(&current_status, finality.status),\n    \"Intent cannot make the verified finality transition\"\n);\n// after\nanyhow::ensure!(\n    intent_nonce == Some(nonce),\n    \"Intent nonce mismatch: stored={intent_nonce:?} finality={nonce}\"\n);\nanyhow::ensure!(\n    execution_transition_allowed(&current_status, finality.status),\n    \"Intent cannot make the verified finality transition: {} -> {}\",\n    current_status, finality.status\n);","handlingStrategy":"type-guard","validationCode":"// Guard the transition before calling the API\nfn can_transition(current: &Status, target: &Status) -> bool {\n    execution_transition_allowed(current, target)\n}\nif !can_transition(&current_status, &finality.status) {\n    // duplicate or out-of-order event: skip instead of failing\n}","typeGuard":"fn is_applicable_finality(current_status: &Status, finality: &VerifiedFinality, stored_nonce: Option<i64>, nonce: i64) -> bool {\n    stored_nonce == Some(nonce)\n        && execution_transition_allowed(current_status, &finality.status)\n}","tryCatchPattern":"match apply_verified_finality(...).await {\n    Err(e) if e.to_string().contains(\"verified finality transition\") => {\n        // treat as duplicate/out-of-order delivery\n        info!(\"finality transition not applicable for intent {}\", finality.intent_id);\n        Ok(())\n    }\n    other => other,\n}","preventionTips":["Make finality application idempotent: track applied transition keys and skip repeats","Deduplicate events at the consumer before invoking the adapter","Keep a single ordered writer per intent for finality messages","Update the transition table whenever status lifecycle changes"],"tags":["state-machine","finality","idempotency","validation"],"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-14T00:17:10.932Z"}