nautechsystems/nautilus_trader · error

Execution intent {} is not prepared for canonical nonce {}

Error message

Execution intent {} is not prepared for canonical nonce {}

What it means

This error is thrown when an UPDATE that assigns a verified execution nonce to an execution intent affects zero rows. It means the intent row with that ID does not exist in a state that can accept the canonical nonce (e.g. missing or already finalized), so the transaction is aborted via anyhow::ensure!.

Source

Thrown at crates/adapters/blockchain/src/cache/database.rs:6030

            .map_err(|e| anyhow::anyhow!("Failed to persist pre-sign verification: {e}"))?;
        }

        let result = sqlx::query(
            "
            UPDATE execution_intent
            SET nonce = $2, updated_at = NOW()
            WHERE id = $1
              AND status = 'prepared'
              AND active
              AND (nonce IS NULL OR nonce = $2)
            ",
        )
        .bind(assignment.intent_id)
        .bind(nonce)
        .execute(&mut *transaction)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to assign verified execution nonce: {e}"))?;
        anyhow::ensure!(
            result.rows_affected() == 1,
            "Execution intent {} is not prepared for canonical nonce {}",
            assignment.intent_id,
            assignment.nonce
        );
        transaction
            .commit()
            .await
            .map_err(|e| anyhow::anyhow!("Failed to commit verified nonce assignment: {e}"))?;
        Ok(())
    }

    /// Appends one verified decision batch before an action on an existing active intent.
    pub(crate) async fn record_execution_verification_batch(
        &self,
        batch: &ExecutionVerificationBatch<'_>,
    ) -> anyhow::Result<()> {
        anyhow::ensure!(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the intent_id exists and is in the prepared state before requesting nonce assignment (query the execution intent table).
  2. Check for concurrent workers assigning nonces to the same intent and add locking or a queue so only one assigner runs.
  3. Re-fetch fresh intent state from this database rather than reusing cached IDs from a previous run or environment.
  4. Inspect the UPDATE's WHERE clause and bindings (intent_id, nonce) to confirm they match the actual row values.

Example fix

// before: assign nonce for a stale id
assign_verified_execution_nonce(&pool, &Assignment { intent_id: stale_id, nonce }).await?;
// after: confirm the intent is still prepared first
let prepared = sqlx::query_scalar::<_, i64>("SELECT 1 FROM execution_intent WHERE intent_id = $1 AND status = 'prepared'")
    .bind(&stale_id).fetch_optional(&pool).await?;
anyhow::ensure!(prepared.is_some(), "intent {stale_id} not prepared");
assign_verified_execution_nonce(&pool, &Assignment { intent_id: stale_id, nonce }).await?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: confirm the intent is prepared before assignment
let prepared = sqlx::query_scalar::<_, i64>(
    "SELECT 1 FROM execution_intent WHERE intent_id = $1 AND status = 'prepared'")
    .bind(&assignment.intent_id)
    .fetch_optional(&pool).await?;
anyhow::ensure!(prepared.is_some(), "intent {} not prepared", assignment.intent_id);

Type guard

fn is_prepared(status: &str) -> bool { status.eq_ignore_ascii_case("prepared") }

Prevention

When it happens

Trigger: Calling the nonce-assignment routine with an intent_id that has no matching prepared execution intent row, or an intent that is no longer in the preparable state when the canonical nonce UPDATE runs.

Common situations: Replaying a nonce assignment after the intent was already processed; a race where another worker consumed or finalized the intent; passing an intent_id from a different database or environment; stale orchestration state after a deploy.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/8f560cf1734af062. Report an issue: GitHub.