nautechsystems/nautilus_trader · error · anyhow::Error

Failed to assign nonce

Error message

Failed to assign nonce {nonce} to execution intent: {e}

What it means

This error is returned by the nonce-assignment database method when the SQL UPDATE that binds a nonce to a prepared execution intent fails at the query level. The anyhow error wraps the underlying sqlx error, so the original cause (connection failure, constraint violation, query error) is embedded in the message. It indicates persistence of the nonce-to-intent mapping could not be completed.

Solutions

  1. Inspect the wrapped sqlx error in the message to identify the root cause (connection vs constraint vs type).
  2. Verify the database is reachable and the pool is healthy (check connection limits, TLS, credentials).
  3. Confirm the execution_intents table schema matches what the query expects (column names and types, especially the nonce column).
  4. Retry the assignment after recovering connectivity; the operation is idempotent as long as the intent is still unassigned.

Example fix

// before: no diagnostics around the call
database.assign_execution_intent_nonce(&intent_id, nonce).await?;
// after: surface the wrapped cause and retry transient failures
match database.assign_execution_intent_nonce(&intent_id, nonce).await {
    Err(e) if is_transient(&e) => { backoff_retry(|| database.assign_execution_intent_nonce(&intent_id, nonce)).await?; }
    Err(e) => { tracing::error!(%nonce, error = %e, "nonce assignment failed"); return Err(e); }
    Ok(()) => {}
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling, confirm DB connectivity and intent existence
let reachable = sqlx::query("SELECT 1").execute(&pool).await.is_ok();
let prepared = sqlx::query("SELECT 1 FROM execution_intents WHERE intent_id = $1 AND nonce IS NULL")
    .bind(intent_id).fetch_optional(&pool).await?.is_some();

Try / catch

match database.assign_execution_intent_nonce(&intent_id, nonce).await {
    Ok(()) => {},
    Err(e) if e.to_string().contains("Failed to assign nonce") => {
        tracing::error!(%nonce, error = %e, "nonce assignment write failed");
        if is_transient(&e) { retry_with_backoff(...).await?; } else { return Err(e); }
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling assign_execution_intent_nonce (database.rs ~5874) when the UPDATE ... SET nonce = $ WHERE intent_id = $ query returns an Err: PostgreSQL connection failure, SQL syntax/type error, transaction aborted, or a database constraint violation during the bind/execute.

Common situations: Database connectivity loss between intent preparation and nonce assignment; the pool being closed or saturated; a schema migration changing the execution intents table columns/types; i32 overflow converting nonce_db; concurrent transactions aborting the update.

Related errors


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

Appendix: source

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

        intent_id: i64,
        nonce: u64,
    ) -> anyhow::Result<()> {
        let nonce_db = i64::try_from(nonce)
            .with_context(|| format!("Execution nonce {nonce} exceeds PostgreSQL BIGINT"))?;
        let result = sqlx::query(
            "
            UPDATE execution_intent
            SET nonce = $2, updated_at = NOW()
            WHERE id = $1
              AND status = 'prepared'
              AND (nonce IS NULL OR nonce = $2)
            ",
        )
        .bind(intent_id)
        .bind(nonce_db)
        .execute(&self.pool)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to assign nonce {nonce} to execution intent: {e}"))?;
        anyhow::ensure!(
            result.rows_affected() == 1,
            "Execution intent {intent_id} is not prepared for nonce {nonce}"
        );
        Ok(())
    }

    /// Assigns the canonical nonce and its authorizing verification evidence atomically.
    ///
    /// # Errors
    ///
    /// Returns an error if the durable nonce ledger, intent ownership, manifest identity, or
    /// evidence is inconsistent, or if persistence fails.
    pub(crate) async fn assign_execution_intent_nonce_verified(
        &self,
        assignment: &ExecutionNonceAssignment<'_>,
    ) -> anyhow::Result<()> {
        anyhow::ensure!(

View on GitHub (pinned to 18893faf8b)