{"record":{"id":"d1d62ffabdf72445","repo":"nautechsystems/nautilus_trader","slug":"execution-intent-intent-id-is-not-prepared-for-n","errorCode":null,"errorMessage":"Execution intent {intent_id} is not prepared for nonce {nonce}","messagePattern":"Execution intent (.+?) is not prepared for nonce (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":5875,"sourceCode":"        nonce: u64,\n    ) -> anyhow::Result<()> {\n        let nonce_db = i64::try_from(nonce)\n            .with_context(|| format!(\"Execution nonce {nonce} exceeds PostgreSQL BIGINT\"))?;\n        let result = sqlx::query(\n            \"\n            UPDATE execution_intent\n            SET nonce = $2, updated_at = NOW()\n            WHERE id = $1\n              AND status = 'prepared'\n              AND (nonce IS NULL OR nonce = $2)\n            \",\n        )\n        .bind(intent_id)\n        .bind(nonce_db)\n        .execute(&self.pool)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to assign nonce {nonce} to execution intent: {e}\"))?;\n        anyhow::ensure!(\n            result.rows_affected() == 1,\n            \"Execution intent {intent_id} is not prepared for nonce {nonce}\"\n        );\n        Ok(())\n    }\n\n    /// Assigns the canonical nonce and its authorizing verification evidence atomically.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the durable nonce ledger, intent ownership, manifest identity, or\n    /// evidence is inconsistent, or if persistence fails.\n    pub(crate) async fn assign_execution_intent_nonce_verified(\n        &self,\n        assignment: &ExecutionNonceAssignment<'_>,\n    ) -> anyhow::Result<()> {\n        anyhow::ensure!(\n            !assignment.decisions.is_empty(),","sourceCodeStart":5857,"sourceCodeEnd":5893,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L5857-L5893","documentation":"This error is raised after the nonce-assignment UPDATE executes successfully but reports rows_affected() != 1, meaning no (or multiple) prepared execution intents matched the given intent_id. It is an integrity check: the intent must exist and be in the prepared state for the nonce to be bound. The invariant is enforced via anyhow::ensure! in database.rs:5875.","triggerScenarios":"Calling the nonce-assignment method with an intent_id that was never prepared (INSERT missing or failed), was already assigned a nonce in a prior call, was deleted/expired between preparation and assignment, or whose row was modified by a concurrent writer so the UPDATE's WHERE clause matched zero rows.","commonSituations":"Double-submission of the same nonce assignment after a retry; calling assignment before the prepare/INSERT step completed; intent rows purged by a cleanup job; mismatched intent_id from a different chain or epoch; concurrent operators racing to assign the same intent.","solutions":["Check the execution_intents table for the intent_id to confirm it exists and is still in the prepared/unassigned state.","Ensure the prepare step (INSERT of the intent) completed successfully before calling nonce assignment.","Make assignment idempotent or add a state guard so retries with an already-assigned intent are detected and treated as success rather than error.","Serialize nonce assignment per intent (DB-level row lock, SELECT ... FOR UPDATE, or application-side per-intent mutex) to prevent racing writers."],"exampleFix":"// before: blind retry loops on this error\nloop { database.assign_execution_intent_nonce(&intent_id, nonce).await?; }\n// after: verify prepared state first, treat already-assigned as success\nlet row = sqlx::query!(\"SELECT nonce FROM execution_intents WHERE intent_id = $1\", intent_id)\n    .fetch_optional(&pool).await?;\nmatch row {\n    Some(r) if r.nonce == Some(nonce_db) => { /* already assigned, idempotent no-op */ }\n    Some(r) if r.nonce.is_none() => database.assign_execution_intent_nonce(&intent_id, nonce).await?,\n    _ => anyhow::bail!(\"intent {intent_id} not in assignable state\"),\n}","handlingStrategy":"validation","validationCode":"// check the intent is present and still assignable before assignment\nlet assignable = sqlx::query(\n    \"SELECT 1 FROM execution_intents WHERE intent_id = $1 AND nonce IS NULL\")\n    .bind(intent_id).fetch_optional(&pool).await?.is_some();\nif !assignable { return Err(anyhow::anyhow!(\"intent {intent_id} missing or already assigned\")); }","typeGuard":null,"tryCatchPattern":"// treat 'not prepared' as an idempotency signal, not a crash\nmatch database.assign_execution_intent_nonce(&intent_id, nonce).await {\n    Err(e) if e.to_string().contains(\"is not prepared for nonce\") => {\n        verify_existing_assignment(&pool, intent_id, nonce)?; // success if already assigned to same nonce\n    }\n    Ok(()) => {},\n    Err(e) => return Err(e),\n}","preventionTips":["Always complete the prepare/INSERT step before nonce assignment.","Make assignment idempotent: detect prior successful assignment of the same nonce.","Serialize assignments per intent_id to avoid concurrent writers.","Watch for cleanup/retention jobs deleting or mutating intent rows mid-flight."],"tags":["database","state-machine","concurrency","idempotency"],"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-23T08:17:48.524Z"}