nautechsystems/nautilus_trader · error · anyhow::Error

Failed to update execution_transaction table: {e}

Error message

Failed to update execution_transaction table: {e}

What it means

This wraps SQLx failures from the UPDATE of execution_transaction that sets a transaction's status by hash (database.rs:7409). The library throws it when the statement fails at the database level; a zero-row update is reported separately by the ensure! that follows, so this error is strictly a query-execution failure.

Source

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

    pub async fn update_execution_transaction_status(
        &self,
        chain_id: u32,
        transaction_hash: &str,
        status: &str,
    ) -> anyhow::Result<()> {
        let result = sqlx::query(
            "
            UPDATE execution_transaction
            SET status = $3
            WHERE chain_id = $1 AND transaction_hash = $2
        ",
        )
        .bind(chain_id as i32)
        .bind(transaction_hash)
        .bind(status)
        .execute(&self.pool)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to update execution_transaction table: {e}"))?;

        anyhow::ensure!(
            result.rows_affected() == 1,
            "Execution transaction {transaction_hash} was not found for status update"
        );
        Ok(())
    }

    /// Loads an execution transaction record by chain ID and transaction hash.
    ///
    /// # Errors
    ///
    /// Returns an error if the database operation fails.
    pub async fn get_execution_transaction(
        &self,
        chain_id: u32,
        transaction_hash: &str,
    ) -> anyhow::Result<Option<ExecutionTransactionRow>> {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the wrapped {e} to identify the root cause (connection, constraint, undefined column).
  2. Apply pending migrations so execution_transaction matches the expected schema.
  3. Validate transaction_hash format and status value fit the column types before the update.
  4. Retry on transient connection/timeout errors; the update is idempotent for the same status.
  5. Check Postgres logs for lock timeouts and reduce contention with concurrent writers.

Example fix

// before: losing the cause by ignoring the error
let _ = db.update_execution_transaction_status(chain_id, &hash, status).await;
// after: surface and retry transient failures
retry(3, backoff, || db.update_execution_transaction_status(chain_id, &hash, status))
    .await.with_context(|| format!("status update for {hash}"))?;
Defensive patterns

Strategy: retry

Validate before calling

let valid = transaction_hash.len() >= 64 && status.len() <= MAX_STATUS_LEN;
anyhow::ensure!(valid, "malformed transaction_hash or status for execution_transaction update");
let exists: Option<i32> = sqlx::query_scalar(
    "SELECT 1 FROM execution_transaction WHERE chain_id = $1 AND transaction_hash = $2")
    .bind(chain_id).bind(transaction_hash).fetch_optional(&pool).await?;

Type guard

fn is_transient_update_error(e: &anyhow::Error) -> bool {
    let s = e.to_string();
    s.contains("connection") || s.contains("timed out") || s.contains("deadlock")
}

Try / catch

match update_result {
    Err(e) if is_transient_update_error(&e) => retry_with_backoff(|| update_status(chain_id, hash, status)).await?,
    Err(e) => return Err(e),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: The UPDATE execution_transaction SET status = $3 WHERE chain_id = $1 AND transaction_hash = $2 fails: connection loss or statement timeout, missing/altered columns from migration drift, value out of range for the status or hash column types, or lock contention until timeout.

Common situations: Adapter schema behind applied code version; Postgres connectivity issues during status updates; extremely long hash strings or unexpected status values failing column constraints; concurrent writers holding locks on the execution_transaction row.

Related errors


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