nautechsystems/nautilus_trader · error
Failed to persist verified action evidence: {e}
Error message
Failed to persist verified action evidence: {e} What it means
The INSERT/UPDATE persisting a verified action-evidence batch into the database failed inside its transaction; the wrapped database error indicates the evidence record (intent, digest, heights, providers) could not be durably stored, aborting the persist step.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:6163
",
)
.bind(batch.intent_id)
.bind(nonce)
.bind(batch.decision_class)
.bind(decision.read_class)
.bind(height_start)
.bind(height_end)
.bind(batch.manifest_version)
.bind(batch.manifest_digest)
.bind(batch.provider_ids)
.bind(batch.operator_ids)
.bind(batch.failure_domain_ids)
.bind(&decision.normalized_value_digest)
.bind(revision)
.bind(transition_key)
.execute(&mut *transaction)
.await
.map_err(|e| anyhow::anyhow!("Failed to persist verified action evidence: {e}"))?;
}
transaction
.commit()
.await
.map_err(|e| anyhow::anyhow!("Failed to commit verified action evidence: {e}"))?;
Ok(())
}
pub(crate) async fn load_execution_replacement_cursor(
&self,
intent_id: i64,
chain_id: u32,
wallet_address: &str,
nonce: u64,
manifest_digest: &str,
) -> anyhow::Result<Option<ExecutionVerifiedHeader>> {
let chain_id = i32::try_from(chain_id)
.context("Replacement scan chain ID exceeds PostgreSQL INTEGER")?;View on GitHub (pinned to 18893faf8b)
Solutions
- Read the inner `{e}` to identify the specific constraint or type error
- Ensure the same (decision_class, intent_id, attempt) evidence is not inserted twice within one batch
- Verify the Rust bind types match the Postgres column types (text[], i64, etc.)
- Re-run migrations if the table schema is older than the code expects
Defensive patterns
Strategy: validation
Validate before calling
// ensure no duplicate evidence rows for this attempt before inserting
let existing: i64 = sqlx::query_scalar(
"SELECT COUNT(*) FROM execution_verification_decision WHERE intent_id=$1 AND decision_class=$2",
).bind(batch.intent_id).bind(batch.decision_class).fetch_one(&pool).await?;
anyhow::ensure!(existing == 0, "evidence already recorded for this attempt"); Try / catch
match result {
Err(e) if e.to_string().contains("duplicate key") => {
// idempotent re-delivery of the same batch; treat as success or skip
}
Err(e) => return Err(e.into()),
Ok(_) => {}
} Prevention
- Match Rust bind types to Postgres column types exactly (text[], bigint)
- Make batch application idempotent via transition_key uniqueness
- Run migrations whenever the manifest/schema changes
- Log the full error chain to identify the failing constraint
When it happens
Trigger: An INSERT INTO execution_verification_decision fails for one decision: constraint violation (e.g. duplicate transition_key), value out of range for a column, type mismatch on arrays (provider_ids/operator_ids/failure_domain_ids), or connection loss.
Common situations: Duplicate transition_key collisions when the same decision_class: intent_id: read_class: attempt: index combination is inserted twice; array element type mismatch between the Rust slice and the Postgres column type; schema drift after a manifest/revision change.
Related errors
- Failed to insert into block table: {e}
- Failed to batch insert into block table: {e}
- Failed to batch insert into pool_event_block table: {e}
- Failed to insert into dex table: {e}
- Failed to insert into pool table: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/f92785bd98d3a7a5.
Report an issue: GitHub.