nautechsystems/nautilus_trader · error · anyhow::Error
Failed to inspect legacy execution transactions: {e}
Error message
Failed to inspect legacy execution transactions: {e} What it means
Thrown when the COUNT(*) over legacy execution_transaction rows with status in ('pending','included','reverted') fails inside ensure_execution_transaction_schema. The table was locked ACCESS EXCLUSIVE moments earlier, so the failure is transport-level: dropped connection, statement timeout scanning a very large table, or the backend being terminated by an admin.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:3247
if let Some(installed_version) = installed_version
&& installed_version > EXECUTION_SCHEMA_VERSION
{
anyhow::bail!(
"Execution schema version {} is newer than supported version {EXECUTION_SCHEMA_VERSION}",
installed_version
);
}
let unresolved_legacy = sqlx::query_scalar::<_, i64>(
"
SELECT COUNT(*)
FROM execution_transaction
WHERE status IN ('pending', 'included', 'reverted')
",
)
.fetch_one(&mut *transaction)
.await
.map_err(|e| anyhow::anyhow!("Failed to inspect legacy execution transactions: {e}"))?;
anyhow::ensure!(
unresolved_legacy == 0,
"Cannot safely migrate {unresolved_legacy} unresolved execution schema version 1 transaction(s); resolve them with the prior version before enabling version {EXECUTION_SCHEMA_VERSION}"
);
for statement in [
"
CREATE OR REPLACE FUNCTION execution_transaction_v2_fence()
RETURNS TRIGGER AS $$
BEGIN
RAISE EXCEPTION 'Legacy execution writer refused after schema version 2 activation';
END;
$$ LANGUAGE plpgsql
",
"DROP TRIGGER IF EXISTS execution_transaction_v2_fence ON execution_transaction",
"
CREATE TRIGGER execution_transaction_v2_fence
BEFORE INSERT OR UPDATE OR DELETE ON execution_transactionView on GitHub (pinned to 2114cf6f76)
Solutions
- Re-run the migration once connectivity is confirmed stable
- Temporarily raise statement_timeout for the migration session
- Archive or trim legacy execution_transaction rows before upgrading
Defensive patterns
Strategy: retry
Validate before calling
-- Estimate scan cost before upgrading SELECT reltuples::bigint AS approx_rows FROM pg_class WHERE relname = 'execution_transaction';
Try / catch
match db.ensure_execution_transaction_schema().await {
Err(e) if e.to_string().contains("statement timeout") || e.to_string().contains("canceling statement") => {
// raise statement_timeout for the session and retry once
}
other => other?,
} Prevention
- Trim or archive legacy execution_transaction rows before major upgrades
- Set statement_timeout appropriate to table size for the migration session
- Monitor connection stability (error rates) before scheduling migrations
When it happens
Trigger: A large legacy execution_transaction table combined with a low statement_timeout; pg_terminate_backend invoked while the count runs; network interruption while the exclusive lock is held.
Common situations: Long-lived nodes with years of transaction history; timeout values tuned for short OLTP queries.
Related errors
- Failed to start execution schema migration: {e}
- Failed to lock legacy execution transactions: {e}
- Failed to migrate execution_transaction table: {e}
- Failed to read execution schema version: {e}
- Cannot safely migrate {unresolved_legacy} unresolved executi
AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21).
Data as JSON: /api/errors/85fa0a748d0449ee.
Report an issue: GitHub.