nautechsystems/nautilus_trader · error · ExecutionIntentReservationError

failed to record prepared execution intent

Error message

failed to record prepared execution intent

What it means

This error is raised when the database insert/update that records a prepared blockchain execution intent (the pre-commit step of reserving an execution intent row) fails. The adapter wraps the underlying sqlx/DB failure in ExecutionIntentReservationError with stage BeforeCommit so callers know the reservation was never committed and the transaction can be safely retried or rolled back.

Source

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

            sqlx::query(
                "
                INSERT INTO execution_transaction_transition (
                    intent_id, transition_key, to_status, block_number
                ) VALUES ($1, 'prepared', 'prepared', $2)
                ",
            )
            .bind(row.id)
            .bind(created_block)
            .execute(&mut *transaction)
            .await
            .context("failed to record prepared execution intent")?;

            Ok::<_, anyhow::Error>((transaction, row))
        }
        .await
        .map_err(|source| {
            anyhow::Error::new(ExecutionIntentReservationError {
                stage: ExecutionIntentReservationStage::BeforeCommit,
                source,
            })
        })?;
        transaction.commit().await.map_err(|e| {
            anyhow::Error::new(ExecutionIntentReservationError {
                stage: ExecutionIntentReservationStage::Commit,
                source: anyhow::Error::new(e)
                    .context("failed to commit execution intent reservation"),
            })
        })?;
        Ok(row)
    }

    /// Assigns the signer nonce to a prepared execution intent.
    ///
    /// Repeating the same assignment is idempotent. A different nonce or non-prepared state
    /// fails closed.

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the wrapped source error (ExecutionIntentReservationError.source) for the actual DB failure cause
  2. Verify database connectivity, credentials, and pool health
  3. Inspect the execution intents table schema/constraints for conflicts (duplicate reservation keys)
  4. Retry the reservation — the BeforeCommit stage means no partial commit occurred
  5. Ensure schema migrations are up to date with the adapter version
Defensive patterns

Strategy: retry

Validate before calling

// Verify DB reachability before attempting a reservation
sqlx::query("SELECT 1").execute(&pool).await
    .map_err(|e| anyhow!("database unreachable: {e}"))?;

Type guard

fn is_before_commit_stage(err: &ExecutionIntentReservationError) -> bool {
    matches!(err.stage, ExecutionIntentReservationStage::BeforeCommit)
}

Try / catch

match reserve_intent(&pool, intent).await {
    Err(e) if is_before_commit_stage(&e) => retry_with_backoff(|| reserve_intent(&pool, intent)),
    other => other,
}

Prevention

When it happens

Trigger: Calling the database's execution-intent reservation routine when the INSERT/UPDATE of the prepared intent row fails inside the open transaction — e.g. constraint violation, connection loss, or lock timeout before transaction.commit() is reached.

Common situations: Postgres restarted or connection pool exhausted mid-transaction; unique/duplicate key conflict on the intent row; schema migration drift between adapter versions; disk-full or permission errors on the database host.

Related errors


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