{"record":{"id":"ba8ada96cf21c4eb","repo":"nautechsystems/nautilus_trader","slug":"no-durable-store-configured-refusing-to-migrate-e","errorCode":null,"errorMessage":"No durable store configured; refusing to migrate execution transaction","messagePattern":"No durable store configured; refusing to migrate execution transaction","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/mod.rs","lineNumber":187,"sourceCode":"                wallet_address,\n                nonce,\n                transaction_hash,\n                purpose,\n                status,\n                client_order_id,\n            )\n            .await\n    }\n\n    /// Migrates the execution transaction table and installs its signer and order uniqueness\n    /// constraints, failing closed when no database is attached.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if no database is configured or the database operation fails.\n    pub async fn ensure_execution_transaction_schema(&self) -> anyhow::Result<()> {\n        let database = self.database.as_ref().ok_or_else(|| {\n            anyhow::anyhow!(\n                \"No durable store configured; refusing to migrate execution transaction\"\n            )\n        })?;\n\n        database.ensure_execution_transaction_schema().await\n    }\n\n    /// Updates the status of a persisted execution transaction record, failing closed when no\n    /// database is attached.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if no database is configured or the database operation fails.\n    pub async fn update_execution_transaction_status(\n        &self,\n        chain_id: u32,\n        transaction_hash: &str,\n        status: &str,","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/2114cf6f761429e0adb5ca9596fcd7b895b16011/crates/adapters/blockchain/src/cache/mod.rs#L169-L205","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Call cache.initialize_database(pg_connect_options).await before ensure_execution_transaction_schema().","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.","Verify Postgres reachability with the same connect options; initialize_database swallows init errors, so prefer connecting via BlockchainCacheDatabase::connect to surface failures.","Assert cache.has_database() immediately after initialization in startup code."],"exampleFix":"// before\nlet mut cache = BlockchainCache::new(chain);\ncache.ensure_execution_transaction_schema().await?; // errors: no durable store\n\n// after\nlet mut cache = BlockchainCache::new(chain);\ncache.initialize_database(pg_connect_options).await;\ncache.ensure_execution_transaction_schema().await?;","handlingStrategy":"validation","validationCode":"// Rust: initialize the store before migrating\nif !cache.has_database() {\n    cache.initialize_database(pg_connect_options).await;\n}\nanyhow::ensure!(cache.has_database(), \"schema migration needs a durable store\");\ncache.ensure_execution_transaction_schema().await?;","typeGuard":"fn is_no_durable_store(e: &anyhow::Error) -> bool {\n    e.to_string().contains(\"No durable store configured\")\n}","tryCatchPattern":"match cache.ensure_execution_transaction_schema().await {\n    Ok(()) => {}\n    Err(e) if is_no_durable_store(&e) => {\n        // ordering bug: initialize_database was never called - abort startup\n        return Err(e.context(\"call initialize_database before schema migration\"));\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Centralize database attach + migration in one startup function so they cannot be reordered.","Prefer BlockchainCacheDatabase::connect for explicit error surfacing over fire-and-forget init.","Add integration tests that boot the cache from scratch to catch missing-init orderings."],"tags":["postgres","migration","schema","configuration","rust"],"backgroundTag":"database-not-configured","analyzedSha":"2114cf6f761429e0adb5ca9596fcd7b895b16011","analyzedAt":"2026-08-21T11:28:30.864Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}