{"record":{"id":"64103cd1a6f4cdb6","repo":"nautechsystems/nautilus_trader","slug":"failed-to-start-signed-transaction-persistence-e","errorCode":null,"errorMessage":"Failed to start signed transaction persistence: {e}","messagePattern":"Failed to start signed transaction persistence: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":6617,"sourceCode":"    }\n\n    async fn add_execution_transaction_payload(\n        &self,\n        intent_id: i64,\n        chain_id: u32,\n        transaction_hash: &str,\n        raw_transaction: Option<&[u8]>,\n        sealed_transaction: Option<&[u8]>,\n    ) -> anyhow::Result<ExecutionTransactionHashRow> {\n        anyhow::ensure!(\n            raw_transaction.is_some() != sealed_transaction.is_some(),\n            \"A signed transaction requires exactly one payload representation\"\n        );\n        let chain_id_db = i32::try_from(chain_id)\n            .with_context(|| format!(\"Chain ID {chain_id} exceeds PostgreSQL INTEGER\"))?;\n        let mut transaction =\n            self.pool.begin().await.map_err(|e| {\n                anyhow::anyhow!(\"Failed to start signed transaction persistence: {e}\")\n            })?;\n\n        if let Some(envelope) = sealed_transaction {\n            let state_row = sqlx::query(\n                \"SELECT deployment_id, protocol_version, operation, active_key_id \\\n                 FROM execution_payload_state WHERE component = 'signed_transactions' FOR SHARE\",\n            )\n            .fetch_optional(&mut *transaction)\n            .await\n            .context(\"failed to lock execution payload state for protected persistence\")?\n            .ok_or_else(|| anyhow::anyhow!(\"Execution payload protection is not active\"))?;\n            let state = execution_payload_state_from_row(&state_row)?;\n            anyhow::ensure!(\n                state.protocol_version == EXECUTION_PAYLOAD_PROTOCOL_VERSION\n                    && state.operation == \"ready\",\n                \"Execution payload storage is not ready for protected persistence\"\n            );\n            anyhow::ensure!(","sourceCodeStart":6599,"sourceCodeEnd":6635,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L6599-L6635","documentation":"In `add_execution_transaction_payload`, after validating the payload representation and chain ID, a database transaction is started via `self.pool.begin()`. This error wraps a failure of that `pool.begin().await` call, meaning no persistence work for the signed transaction was attempted — the transaction never started.","triggerScenarios":"`self.pool.begin()` fails: the connection pool is exhausted (all connections checked out), the pool cannot acquire a healthy connection within `acquire_timeout`, the database is unreachable, credentials were rejected at connect time, or the database is starting up/shutting down.","commonSituations":"Postgres down or restarting when a signed transaction is persisted before broadcast; pool max_connections too small for concurrent execution workers; network partition or firewall dropping pooled idle connections; wrong DATABASE_URL after a config change.","solutions":["Verify database reachability and credentials (DATABASE_URL) and that Postgres is accepting connections","Increase sqlx pool capacity/tune `acquire_timeout` if the pool is exhausted under broadcast load","Retry the call — starting a transaction is safe to retry since nothing was persisted","Check pool metrics/logs for connection acquisition timeouts and set max_lifetime below any intermediary TCP idle timeout"],"exampleFix":"// before\nlet mut transaction = self.pool.begin().await.map_err(|e| {\n    anyhow::anyhow!(\"Failed to start signed transaction persistence: {e}\")\n})?;\n// after\nlet mut transaction = self.pool.begin().await.with_context(|| {\n    format!(\"Failed to start signed transaction persistence for intent {intent_id}: pool status: {}\", self.pool.size())\n})?;","handlingStrategy":"retry","validationCode":"// Verify pool connectivity before persisting\nsqlx::query(\"SELECT 1\").execute(&db.pool).await\n    .context(\"database pool unavailable for signed transaction persistence\")?;","typeGuard":null,"tryCatchPattern":"let mut transaction = loop {\n    match db.pool.begin().await {\n        Ok(tx) => break tx,\n        Err(e) if attempts < 3 => { attempts += 1; tokio::time::sleep(backoff).await; }\n        Err(e) => return Err(anyhow::anyhow!(\"Failed to start signed transaction persistence: {e}\")),\n    }\n};","preventionTips":["Keep the sqlx pool warm and sized for concurrent broadcast workers (min_connections, max_connections)","Set acquire_timeout generously enough for burst load but below caller-level timeouts","Set pool max_lifetime below any NAT/firewall idle timeout on the DB path","Alert on pool acquisition wait times so exhaustion is caught before it errors"],"tags":["database","sqlx","connection-pool","persistence"],"backgroundTag":"database-query-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}