nautechsystems/nautilus_trader · error · anyhow::Error
Failed to commit execution transition
Error message
Failed to commit execution transition: {e} What it means
Raised when transaction.commit() fails after all statements in the execution-status transition succeeded. Nothing is persisted (the transaction rolls back implicitly), even though row locks, validation, and writes all passed locally. This typically indicates the connection to the database was lost between the last statement and the commit.
Solutions
- Retry the entire transition with backoff — the rollback left state consistent, so a retry is safe.
- Shorten the transaction (do non-critical work outside it) to stay under idle-in-transaction timeouts.
- Tune Postgres idle_in_transaction_session_timeout and the pool's acquire/idle timeouts for the workload.
- Check server logs for 'terminating connection' or deadlock messages at the failure timestamp.
Example fix
// before
transaction.commit().await.map_err(|e| anyhow::anyhow!("Failed to commit execution transition: {e}"))?;
// after
if let Err(e) = transaction.commit().await {
tracing::warn!(error = %e, "commit failed; state unchanged, safe to retry");
return Err(anyhow::anyhow!("Failed to commit execution transition: {e}"));
} Defensive patterns
Strategy: retry
Try / catch
loop {
match transition.await {
Ok(()) => break,
Err(e) if e.to_string().contains("Failed to commit execution transition") && attempts < MAX_RETRIES => {
attempts += 1;
tokio::time::sleep(backoff.next()).await; // rollback left state consistent
}
Err(e) => return Err(e),
}
} Prevention
- Tune idle_in_transaction_session_timeout above worst-case lock wait times.
- Do heavy work (receipt parsing, hashing) before BEGIN, not inside the transaction.
- Enable TCP keepalives on the database connection to survive NAT/firewall idle drops.
- Retries are safe: a failed COMMIT rolls everything back atomically.
When it happens
Trigger: Calling the transition when COMMIT fails: network drop or database restart mid-transaction, idle_in_transaction_session_timeout terminating the session after long lock waits, admin-initiated pg_terminate_backend, or serialization/deadlock detection aborting the commit.
Common situations: Long lock contention on the intent row (another worker holding FOR UPDATE) pushing past the session timeout; database failover during receipt processing; firewall/NAT dropping idle connections between statements.
Related errors
- Failed to commit verified action evidence
- Failed to commit verified finality transition
- Failed to advance canonical nonce ledger
- Failed to commit add_account transaction
- Failed to commit order client origins
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7704165812654471.
Report an issue: GitHub.
Appendix: source
Thrown at crates/adapters/blockchain/src/cache/database.rs:6881
WHERE intent_id = $1 AND transaction_hash = $2
ON CONFLICT (intent_id, transition_key) DO NOTHING
",
)
.bind(intent_id)
.bind(transaction_hash)
.bind(transition_key)
.bind(current_status)
.bind(status.as_str())
.bind(block_number_db)
.bind(block_hash)
.execute(&mut *transaction)
.await
.map_err(|e| anyhow::anyhow!("Failed to record execution transition: {e}"))?;
transaction
.commit()
.await
.map_err(|e| anyhow::anyhow!("Failed to commit execution transition: {e}"))?;
Ok(())
}
/// Records verified final consumption and advances the canonical nonce in one transaction.
///
/// # Errors
///
/// Returns an error if the receipt transition, nonce ledger, manifest identity, or evidence
/// is inconsistent, or if persistence fails.
pub(crate) async fn record_execution_finality_verified(
&self,
finality: &ExecutionFinalityTransition<'_>,
) -> anyhow::Result<()> {
anyhow::ensure!(
matches!(
finality.status,
TransactionStatus::Finalized | TransactionStatus::Reverted
),View on GitHub (pinned to 18893faf8b)