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 uniquenessView on GitHub (pinned to 2114cf6f76)
Solutions
- Set BlockchainExecutionClientConfig::postgres_cache_database_config (PostgresConnectOptions) before constructing/connecting the execution client.
- If using BlockchainCache directly, call cache.initialize_database(pg_connect_options).await before any execution-transaction write.
- Confirm connect() succeeded; a failed Postgres connect surfaces earlier as "Failed to connect to the Postgres cache database".
- 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
- Assert cache.has_database() (or client config has postgres options) as a hard startup check.
- Treat a missing durable store as a boot-time failure for any deployment that will trade.
- Watch connect() logs for the 'No Postgres cache database configured' warning and alert on it.
- Keep one canonical config builder that always sets postgres_cache_database_config.
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
- No durable store configured; refusing to submit a transactio
- No durable store configured for execution reconciliation
- Execution schema version {} is newer than supported version
- Failed to update execution hash {transaction_hash}: {e}
- Execution transaction hash {transaction_hash} was not found
AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21).
Data as JSON: /api/errors/559d15fa9bb91d39.
Report an issue: GitHub.