nautechsystems/nautilus_trader · error · anyhow::Error
Execution transaction {transaction_hash} was not found for s
Error message
Execution transaction {transaction_hash} was not found for status update What it means
This error is raised when an UPDATE on the `execution_transaction` table affected zero rows, meaning no row exists for the given transaction hash. The library enforces `rows_affected() == 1` after the status-update statement to guarantee the caller only advances statuses of transactions it previously persisted. It is an existence guard against silently updating nothing.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:7411
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>> {
let chain_id_db = i32::try_from(chain_id)
.with_context(|| format!("Chain ID {chain_id} exceeds PostgreSQL INTEGER"))?;View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the transaction hash was previously inserted into execution_transaction for the same chain_id before updating its status
- Check whether a retention/cleanup job deleted the row while the status update was in flight
- Confirm you are connected to the same database/schema the transaction was written to
- If the transaction may legitimately be absent, check existence first with a SELECT and skip the update instead of updating blindly
Example fix
// before
update_status(&db, &missing_hash, Status::Confirmed).await?;
// after
if db.execution_transaction_exists(chain_id, &missing_hash).await? {
update_status(&db, &missing_hash, Status::Confirmed).await?;
} else {
tracing::warn!(hash=%missing_hash, "skipping status update for unknown execution transaction");
} Defensive patterns
Strategy: validation
Validate before calling
let exists: bool = sqlx::query_scalar("SELECT EXISTS(SELECT 1 FROM execution_transaction WHERE chain_id = $1 AND transaction_hash = $2)")
.bind(chain_id).bind(&tx_hash).fetch_one(&pool).await?;
if !exists { skip_or_insert(); } Prevention
- Always insert the execution transaction row before issuing status updates
- Track hashes only from the same chain/database they were persisted to
- Coordinate retention/cleanup jobs with in-flight status updates
When it happens
Trigger: Calling the transaction status update method with a transaction_hash that was never inserted into execution_transaction, or updating a row that was deleted concurrently.
Common situations: A consumer tracks a transaction hash from a different chain/database than the cache DB being updated; the row was pruned by retention/cleanup before the status callback arrived; a hash is passed from an unverified event source; replaying events after a database reset.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- Implement FromRow for FuturesSpread
- Implement FromRow for OptionSpread
- Failed to load account events: {e}
- Failed to load from execution_transaction table: {e}
- Failed to load instruments: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/863b58327c8d4b5d.
Report an issue: GitHub.