nautechsystems/nautilus_trader · error · anyhow::Error

Failed to record verified finality receipt: {e}

Error message

Failed to record verified finality receipt: {e}

What it means

Wraps a sqlx failure on the UPDATE/INSERT that records the verified finality receipt (block_hash, receipt_success, gas_used, effective_gas_price) — the adjacent statement updates `execution_transaction_hash` status. A failure aborts the finality transaction before the subsequent rows_affected check can run. The underlying database error is embedded via `{e}`.

Source

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

            "
            UPDATE execution_transaction_hash
            SET status = $3, block_number = $4, block_hash = $5,
                receipt_success = $6, gas_used = $7, effective_gas_price = $8,
                updated_at = NOW()
            WHERE intent_id = $1 AND transaction_hash = $2
            ",
        )
        .bind(finality.intent_id)
        .bind(finality.transaction_hash)
        .bind(finality.status.as_str())
        .bind(block_number)
        .bind(finality.block_hash)
        .bind(finality.receipt_success)
        .bind(gas_used)
        .bind(finality.effective_gas_price)
        .execute(&mut *transaction)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to record verified finality receipt: {e}"))?;
        anyhow::ensure!(
            hash_result.rows_affected() == 1,
            "Finality transaction hash was not found"
        );

        let active = !fill_emitted && !terminal_emitted;
        sqlx::query(
            "UPDATE execution_intent SET status = $2, active = $3, updated_at = NOW() WHERE id = $1",
        )
        .bind(finality.intent_id)
        .bind(finality.status.as_str())
        .bind(active)
        .execute(&mut *transaction)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to record verified finality intent: {e}"))?;

        let transition_key = format!(
            "{}:{}:{}:{}",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the interpolated `{e}` to identify the exact sqlx/Postgres failure
  2. Verify receipt table schema (columns and numeric types for gas_used/effective_gas_price) matches current migrations
  3. Shorten the surrounding transaction and check for lock contention on the same transaction hash rows
  4. Confirm database connectivity and pool health
  5. Check numeric ranges of gas fields fit the column types
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify receipt fields fit before persisting
let ok = finality.block_number >= 0
    && gas_used >= 0
    && !finality.transaction_hash.is_empty();

Type guard

fn receipt_is_recordable(finality: &VerifiedFinality, gas_used: i64) -> bool {
    !finality.transaction_hash.is_empty()
        && !finality.block_hash.is_empty()
        && gas_used >= 0
}

Try / catch

match record_finality_receipt(...).await {
    Err(e) if is_transient_db_error(&e) => retry_with_backoff(3, || record_finality_receipt(...)),
    Err(e) => return Err(e),
    Ok(()) => {},
}

Prevention

When it happens

Trigger: The receipt-recording statement fails: connection loss mid-transaction, schema mismatch on receipt columns, invalid gas_used/effective_gas_price encoding, lock contention on the receipt or transaction-hash rows, or statement timeout.

Common situations: Schema drift after an adapter upgrade adding receipt columns; gas values exceeding column bounds (e.g. i32 vs i64); concurrent writers updating the same transaction-hash row causing lock waits; pool exhaustion during a burst of finalized blocks.

Related errors


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