nautechsystems/nautilus_trader · error · anyhow::Error

No durable store configured; refusing to migrate execution t

Error message

No durable store configured; refusing to migrate execution transaction

What it means

BlockchainCache::ensure_execution_transaction_schema (crates/adapters/blockchain/src/cache/mod.rs:187) refuses to run the execution_transaction migration and install its signer/order uniqueness constraints when no database is attached (database field is None). Schema migration is a durable-store operation, so the method fails closed rather than pretending the schema exists. Inside the execution client this migration runs during connect() only after a Postgres store was successfully attached; hitting this error means the migration path was invoked on a store-less cache.

Source

Thrown at crates/adapters/blockchain/src/cache/mod.rs:187

                wallet_address,
                nonce,
                transaction_hash,
                purpose,
                status,
                client_order_id,
            )
            .await
    }

    /// Migrates the execution transaction table and installs its signer and order uniqueness
    /// constraints, failing closed when no database is attached.
    ///
    /// # Errors
    ///
    /// Returns an error if no database is configured or the database operation fails.
    pub async fn ensure_execution_transaction_schema(&self) -> anyhow::Result<()> {
        let database = self.database.as_ref().ok_or_else(|| {
            anyhow::anyhow!(
                "No durable store configured; refusing to migrate execution transaction"
            )
        })?;

        database.ensure_execution_transaction_schema().await
    }

    /// Updates the status of a persisted execution transaction record, failing closed when no
    /// database is attached.
    ///
    /// # Errors
    ///
    /// Returns an error if no database is configured or the database operation fails.
    pub async fn update_execution_transaction_status(
        &self,
        chain_id: u32,
        transaction_hash: &str,
        status: &str,

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Call cache.initialize_database(pg_connect_options).await before ensure_execution_transaction_schema().
  2. For the execution client, set postgres_cache_database_database_config-free equivalent: postgres_cache_database_config in BlockchainExecutionClientConfig so connect() attaches the store and runs the migration itself.
  3. Verify Postgres reachability with the same connect options; initialize_database swallows init errors, so prefer connecting via BlockchainCacheDatabase::connect to surface failures.
  4. Assert cache.has_database() immediately after initialization in startup code.

Example fix

// before
let mut cache = BlockchainCache::new(chain);
cache.ensure_execution_transaction_schema().await?; // errors: no durable store

// after
let mut cache = BlockchainCache::new(chain);
cache.initialize_database(pg_connect_options).await;
cache.ensure_execution_transaction_schema().await?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: initialize the store before migrating
if !cache.has_database() {
    cache.initialize_database(pg_connect_options).await;
}
anyhow::ensure!(cache.has_database(), "schema migration needs a durable store");
cache.ensure_execution_transaction_schema().await?;

Type guard

fn is_no_durable_store(e: &anyhow::Error) -> bool {
    e.to_string().contains("No durable store configured")
}

Try / catch

match cache.ensure_execution_transaction_schema().await {
    Ok(()) => {}
    Err(e) if is_no_durable_store(&e) => {
        // ordering bug: initialize_database was never called - abort startup
        return Err(e.context("call initialize_database before schema migration"));
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling ensure_execution_transaction_schema on a BlockchainCache built with new(chain) and never initialized with initialize_database; invoking the migration before Postgres options were configured while the execution client skips it silently (connect logs the no-durable-store warning when postgres_cache_database_config is None).

Common situations: Bootstrapping scripts that try to pre-migrate the schema before establishing the database connection; reordered startup code that runs migrations against an uninitialized cache; environments where the Postgres URL env var is missing so the config field stays None.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/ba8ada96cf21c4eb. Report an issue: GitHub.