nautechsystems/nautilus_trader · error · anyhow::Error
Failed to persist signed transaction {transaction_hash}: {e}
Error message
Failed to persist signed transaction {transaction_hash}: {e} What it means
The INSERT ... ON CONFLICT statement that persists the signed transaction row failed with a database error. The library wraps the sqlx error with the transaction hash so the operator knows which signed payload failed to persist. This aborts the enclosing transaction, so nothing (including the intent status update) is committed.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:6706
AND execution_transaction_hash.sealed_transaction IS NOT NULL
)
)
RETURNING
id, intent_id, chain_id, transaction_hash, payload_expected,
raw_transaction, sealed_transaction, status,
block_number, block_hash, receipt_success, gas_used,
effective_gas_price, current
",
)
.bind(intent_id)
.bind(chain_id_db)
.bind(transaction_hash)
.bind(raw_transaction)
.bind(sealed_transaction)
.fetch_optional(&mut *transaction)
.await
.map_err(|e| {
anyhow::anyhow!("Failed to persist signed transaction {transaction_hash}: {e}")
})?
.ok_or_else(|| {
anyhow::anyhow!(
"Signed transaction {transaction_hash} conflicts with its persisted identity"
)
})?;
sqlx::query(
"UPDATE execution_intent SET status = 'signed', updated_at = NOW() WHERE id = $1",
)
.bind(intent_id)
.execute(&mut *transaction)
.await
.map_err(|e| anyhow::anyhow!("Failed to mark execution intent signed: {e}"))?;
sqlx::query(
"
INSERT INTO execution_transaction_transition (
intent_id, transaction_hash_id, transition_key, from_status, to_statusView on GitHub (pinned to 18893faf8b)
Solutions
- Read the inner sqlx error (the {e} in the message) — it names the precise SQL failure; fix that root cause.
- Retry with backoff for transient errors (connection, deadlock, serialization) — the operation is transactional and safe to redo.
- Ensure the intent has a nonce set before persisting, and that chain_id fits PostgreSQL INTEGER.
- Check pg_stat_activity for blocking transactions if timeouts/deadlocks recur.
Defensive patterns
Strategy: retry
Validate before calling
// ensure intent has a nonce (required by the INSERT's WHERE clause) and chain_id fits i32
let nonce: Option<i64> = sqlx::query_scalar("SELECT nonce FROM execution_intent WHERE id=$1").bind(intent_id).fetch_one(&pool).await?;
anyhow::ensure!(nonce.is_some(), "intent must have a nonce before persisting a signed transaction"); Try / catch
let row = retry_if(3, || db.add_execution_transaction(...), |e| {
let s = e.to_string();
s.contains("Failed to persist signed transaction") && is_transient(&s)
}).await?; Prevention
- Read the wrapped inner sqlx error to target the real cause (timeout, deadlock, constraint)
- Classify transient vs permanent DB errors and only retry the former
- Bound raw/sealed payload sizes to avoid bytea/statement limits
- Keep chain_id within PostgreSQL INTEGER range before calling
When it happens
Trigger: The INSERT into execution_transaction_hash errored: connection drop, statement timeout, a SQL-level failure such as type/integer overflow on chain_id or serialization failure, or deadlock with a concurrent writer. Note: zero rows from the INSERT's SELECT WHERE clause (intent missing nonce) is the distinct conflict error, not this one.
Common situations: Network interruption to PostgreSQL mid-transaction; concurrent signing workers deadlocking on the same chain/hash rows; oversized raw_transaction bytea exceeding field/server limits; database under load causing timeouts.
Related errors
- Failed to activate execution schema version 2: {e}
- Failed to install verification schema: {e}
- Failed to mark execution intent signed: {e}
- Failed to record signed transaction transition: {e}
- Error executing statement {sql_statement} with error: {e:?}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ad1a8b67c55eea5f.
Report an issue: GitHub.