nautechsystems/nautilus_trader · error · anyhow::Error

No durable store configured; refusing to persist execution t

Error message

No durable store configured; refusing to persist execution transaction

What it means

BlockchainCache::add_execution_transaction (crates/adapters/blockchain/src/cache/mod.rs:161) fails closed when the cache has no attached durable store: the database: Option<BlockchainCacheDatabase> field is None, so the method refuses to persist an execution transaction instead of silently dropping the record. A database is only attached via BlockchainCache::initialize_database(PgConnectOptions), or automatically by BlockchainExecutionClient::connect when config.postgres_cache_database_config is set. This is an intentional safety design: durable transaction records are mandatory for crash recovery, so a missing store aborts the write path.

Source

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

    /// # Errors
    ///
    /// Returns an error if no database is configured or the database operation fails.
    #[expect(
        clippy::too_many_arguments,
        reason = "the parameters mirror the persisted execution transaction fields"
    )]
    pub async fn add_execution_transaction(
        &self,
        chain_id: u32,
        wallet_address: &str,
        nonce: u64,
        transaction_hash: &str,
        purpose: &str,
        status: &str,
        client_order_id: Option<&str>,
    ) -> anyhow::Result<()> {
        let database = self.database.as_ref().ok_or_else(|| {
            anyhow::anyhow!(
                "No durable store configured; refusing to persist execution transaction"
            )
        })?;

        database
            .add_execution_transaction(
                chain_id,
                wallet_address,
                nonce,
                transaction_hash,
                purpose,
                status,
                client_order_id,
            )
            .await
    }

    /// Migrates the execution transaction table and installs its signer and order uniqueness

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Set BlockchainExecutionClientConfig::postgres_cache_database_config (PostgresConnectOptions) before constructing/connecting the execution client.
  2. If using BlockchainCache directly, call cache.initialize_database(pg_connect_options).await before any execution-transaction write.
  3. Confirm connect() succeeded; a failed Postgres connect surfaces earlier as "Failed to connect to the Postgres cache database".
  4. Add a startup assertion on cache.has_database() so misconfiguration fails fast at boot instead of at first submission.

Example fix

// before
let mut cache = BlockchainCache::new(chain);
cache.add_execution_transaction(chain_id, wallet, nonce, tx_hash, purpose, status, None).await?; // errors: no durable store

// after
let mut cache = BlockchainCache::new(chain);
cache.initialize_database(pg_connect_options).await;
assert!(cache.has_database());
cache.add_execution_transaction(chain_id, wallet, nonce, tx_hash, purpose, status, None).await?;
Defensive patterns

Strategy: validation

Validate before calling

// Rust: attach a durable store before any execution-transaction write
if !cache.has_database() {
    cache.initialize_database(pg_connect_options).await;
}
anyhow::ensure!(
    cache.has_database(),
    "cannot persist execution transactions without Postgres"
);

Type guard

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

Try / catch

if let Err(e) = cache.add_execution_transaction(/* ... */).await {
    if is_no_durable_store(&e) {
        // configuration bug: fail loudly at startup instead of retrying
        return Err(e.context("execution persistence requires postgres_cache_database_config"));
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Calling add_execution_transaction on a cache constructed with BlockchainCache::new(chain) without ever calling initialize_database; running the execution client with postgres_cache_database_config: None (connect logs the warning "No Postgres cache database configured; transactions will be refused") and then submitting an order, wrap, or approve which tries to persist its transaction record.

Common situations: Postgres connection settings omitted from the environment/config file in a new deployment; a staging config copied to production with the database section stripped; running in memory-only mode by design but still invoking durable-write APIs; Postgres configured but connect() was never called, so the cache never attached a store.

Related errors


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