nautechsystems/nautilus_trader · error · anyhow::Error

Failed to record verified finality intent: {e}

Error message

Failed to record verified finality intent: {e}

What it means

Wraps a sqlx failure on the final UPDATE that records the verified finality state on the intent row (status = finality.status, active flag). This is the last state write of the finality commit; failing it rolls back the entire transaction so headers, verifications, receipt, and hash updates are all discarded. The database error text is embedded via `{e}`.

Source

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

        .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!(
            "{}:{}:{}:{}",
            finality.status.as_str(),
            finality.transaction_hash,
            finality.block_number,
            finality.block_hash
        );
        sqlx::query(
            "
            INSERT INTO execution_transaction_transition (
                intent_id, transaction_hash_id, transition_key, from_status, to_status,
                block_number, block_hash
            )
            SELECT $1, id, $3, $4, $5, $6, $7
            FROM execution_transaction_hash
            WHERE intent_id = $1 AND transaction_hash = $2
            ",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the embedded `{e}` for the exact Postgres error
  2. If it is a lock timeout, reduce transaction duration or retry finality application with backoff
  3. Check any CHECK/enum constraints on the status column accept the new status value
  4. Apply pending migrations so status/active columns match the adapter's expectations
  5. Verify pool/connectivity health if failures cluster at the end of long transactions
Defensive patterns

Strategy: retry

Validate before calling

// Confirm the status value is acceptable before the final write
let valid = allowed_statuses().contains(&finality.status.as_str().to_string());
if !valid { /* reject earlier, before the transaction begins */ }

Try / catch

match result {
    Err(e) if is_transient_db_error(&e) || is_lock_timeout(&e) => {
        retry_with_backoff(3, || apply_verified_finality(...)).await
    }
    Err(e) => Err(e),
    Ok(v) => Ok(v),
}

Prevention

When it happens

Trigger: The intent-status UPDATE fails: connection loss at the end of a long transaction, lock contention on the intent row, schema drift on status/active columns, or an invalid value for the status enum/text column.

Common situations: Long finality transactions hitting idle-in-transaction timeouts right at the final write; concurrent processors holding a lock on the same intent row; an adapter upgrade adding new status values not accepted by a DB CHECK constraint; pool exhaustion during batch finalization.

Related errors


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