nautechsystems/nautilus_trader · error · anyhow::Error

Failed to inspect recoverable signed executions: {e}

Error message

Failed to inspect recoverable signed executions: {e}

What it means

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.

Source

Thrown at crates/adapters/blockchain/src/cache/database.rs:7321

            .with_context(|| format!("Chain ID {chain_id} exceeds PostgreSQL INTEGER"))?;
        sqlx::query_scalar::<_, bool>(
            "
            SELECT EXISTS (
                SELECT 1
                FROM execution_intent AS intent
                JOIN execution_transaction_hash AS hash ON hash.intent_id = intent.id
                WHERE intent.chain_id = $1
                  AND intent.wallet_address = $2
                  AND intent.status = 'recoverable'
                  AND (hash.raw_transaction IS NOT NULL OR hash.sealed_transaction IS NOT NULL)
            )
            ",
        )
        .bind(chain_id_db)
        .bind(wallet_address)
        .fetch_one(&self.pool)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to inspect recoverable signed executions: {e}"))
    }

    /// Loads all transaction hashes for an intent in insertion order.
    ///
    /// # Errors
    ///
    /// Returns an error if the query fails.
    pub async fn get_execution_transaction_hashes(
        &self,
        intent_id: i64,
    ) -> anyhow::Result<Vec<ExecutionTransactionHashRow>> {
        sqlx::query_as::<_, ExecutionTransactionHashRow>(
            "
            SELECT
                id, intent_id, chain_id, transaction_hash, payload_expected,
                raw_transaction, sealed_transaction, status,
                block_number, block_hash, receipt_success, gas_used,
                effective_gas_price, current

View on GitHub (pinned to 18893faf8b)

Solutions

  1. 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).
  2. Read the wrapped {e} for driver-level causes; retry on transient connection/timeout errors.
  3. Run pending migrations to ensure the queried tables exist.
  4. Normalize the wallet address format (same case/encoding as stored) and verify chain_id matches the stored rows.
  5. Check Postgres logs if failures correlate with load or failover.

Example fix

// before: fetch_one that errors when no row exists
let state = sqlx::query(...).fetch_one(&pool).await.map_err(...)?;
// after: handle the empty case explicitly
let state = sqlx::query_as::<_, RecoverableState>(...).fetch_optional(&pool).await?;
let state = state.ok_or_else(|| anyhow!("no recoverable execution state for {wallet} on chain {chain_id}"))?;
Defensive patterns

Strategy: try-catch

Validate before calling

let row_exists: Option<i32> = sqlx::query_scalar(
    "SELECT 1 FROM execution_verification_nonce WHERE chain_id = $1 AND wallet_address = $2")
    .bind(chain_id_db).bind(wallet).fetch_optional(&pool).await?;
anyhow::ensure!(row_exists.is_some(), "no recoverable-execution state for {wallet} on chain {chain_id}");

Type guard

fn is_row_not_found(e: &anyhow::Error) -> bool {
    e.chain().any(|c| c.to_string().contains("no rows returned"))
}

Try / catch

match inspect_result {
    Err(e) if is_row_not_found(&e) => initialize_wallet_state(chain_id, wallet).await?,
    Err(e) if is_transient(&e) => retry_with_backoff(...).await?,
    other => other?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/5d1c25d13e7f2dd3. Report an issue: GitHub.