{"record":{"id":"5d1c25d13e7f2dd3","repo":"nautechsystems/nautilus_trader","slug":"failed-to-inspect-recoverable-signed-executions","errorCode":null,"errorMessage":"Failed to inspect recoverable signed executions: {e}","messagePattern":"Failed to inspect recoverable signed executions: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":7321,"sourceCode":"            .with_context(|| format!(\"Chain ID {chain_id} exceeds PostgreSQL INTEGER\"))?;\n        sqlx::query_scalar::<_, bool>(\n            \"\n            SELECT EXISTS (\n                SELECT 1\n                FROM execution_intent AS intent\n                JOIN execution_transaction_hash AS hash ON hash.intent_id = intent.id\n                WHERE intent.chain_id = $1\n                  AND intent.wallet_address = $2\n                  AND intent.status = 'recoverable'\n                  AND (hash.raw_transaction IS NOT NULL OR hash.sealed_transaction IS NOT NULL)\n            )\n            \",\n        )\n        .bind(chain_id_db)\n        .bind(wallet_address)\n        .fetch_one(&self.pool)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to inspect recoverable signed executions: {e}\"))\n    }\n\n    /// Loads all transaction hashes for an intent in insertion order.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the query fails.\n    pub async fn get_execution_transaction_hashes(\n        &self,\n        intent_id: i64,\n    ) -> anyhow::Result<Vec<ExecutionTransactionHashRow>> {\n        sqlx::query_as::<_, ExecutionTransactionHashRow>(\n            \"\n            SELECT\n                id, intent_id, chain_id, transaction_hash, payload_expected,\n                raw_transaction, sealed_transaction, status,\n                block_number, block_hash, receipt_success, gas_used,\n                effective_gas_price, current","sourceCodeStart":7303,"sourceCodeEnd":7339,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L7303-L7339","documentation":"This wraps a SQLx failure from the query that inspects whether a signed execution is recoverable for a chain/wallet pair, ending in fetch_one (database.rs:7321). fetch_one additionally errors when the query returns zero rows, so besides genuine database failures, an empty result set (no nonce ledger / intent row for that chain + wallet) surfaces as this error.","triggerScenarios":"The inspection query fails at the driver level (connection loss, timeout, undefined table after missed migration), or fetch_one receives 0 rows because no execution_verification_nonce/intent row exists yet for the given chain_id + wallet_address.","commonSituations":"Querying recovery state for a wallet that has never had a signed execution; pointing the adapter at a database where migrations were not applied; transient connectivity loss; passing a chain_id or wallet address that differs from how it was stored (e.g. checksummed vs lowercase).","solutions":["If the wrapped message indicates RowNotFound, first confirm a ledger/intent row exists for that chain_id + wallet_address (initialize it if the wallet is new).","Read the wrapped {e} for driver-level causes; retry on transient connection/timeout errors.","Run pending migrations to ensure the queried tables exist.","Normalize the wallet address format (same case/encoding as stored) and verify chain_id matches the stored rows.","Check Postgres logs if failures correlate with load or failover."],"exampleFix":"// before: fetch_one that errors when no row exists\nlet state = sqlx::query(...).fetch_one(&pool).await.map_err(...)?;\n// after: handle the empty case explicitly\nlet state = sqlx::query_as::<_, RecoverableState>(...).fetch_optional(&pool).await?;\nlet state = state.ok_or_else(|| anyhow!(\"no recoverable execution state for {wallet} on chain {chain_id}\"))?;","handlingStrategy":"try-catch","validationCode":"let row_exists: Option<i32> = sqlx::query_scalar(\n    \"SELECT 1 FROM execution_verification_nonce WHERE chain_id = $1 AND wallet_address = $2\")\n    .bind(chain_id_db).bind(wallet).fetch_optional(&pool).await?;\nanyhow::ensure!(row_exists.is_some(), \"no recoverable-execution state for {wallet} on chain {chain_id}\");","typeGuard":"fn is_row_not_found(e: &anyhow::Error) -> bool {\n    e.chain().any(|c| c.to_string().contains(\"no rows returned\"))\n}","tryCatchPattern":"match inspect_result {\n    Err(e) if is_row_not_found(&e) => initialize_wallet_state(chain_id, wallet).await?,\n    Err(e) if is_transient(&e) => retry_with_backoff(...).await?,\n    other => other?,\n}","preventionTips":["Initialize ledger/state rows when a wallet is first used so inspection never sees zero rows.","Prefer fetch_optional in caller-side code to distinguish 'empty' from 'failed'.","Normalize address format and chain_id before querying.","Run migrations on every environment before deploying adapter updates."],"tags":["database","sqlx","recovery","query"],"backgroundTag":"sql-query-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}