nautechsystems/nautilus_trader · error · anyhow::Error

Failed to commit execution schema migration: {e}

Error message

Failed to commit execution schema migration: {e}

What it means

Thrown when the final COMMIT of the schema-v2 migration transaction fails in ensure_execution_transaction_schema. The exclusive lock, all DDL, and the version upsert roll back, leaving the database at v1. Causes are transport-level: connection dropped at commit, Postgres restart or failover, or a proxy killing the session.

Source

Thrown at crates/adapters/blockchain/src/cache/database.rs:3300

            "
            INSERT INTO execution_schema_version (component, version)
            VALUES ('evm_execution', 2)
            ON CONFLICT (component) DO UPDATE SET version = EXCLUDED.version
            WHERE execution_schema_version.version <= EXCLUDED.version
            ",
        ] {
            sqlx::query(statement)
                .execute(&mut *transaction)
                .await
                .map_err(|e| {
                    anyhow::anyhow!("Failed to activate execution schema version 2: {e}")
                })?;
        }

        transaction
            .commit()
            .await
            .map_err(|e| anyhow::anyhow!("Failed to commit execution schema migration: {e}"))?;

        Ok(())
    }

    /// Reserves durable ownership of a signer slot and optional client order before signing.
    ///
    /// # Errors
    ///
    /// Returns an error if the signer or client order is already owned, or persistence fails.
    pub async fn reserve_execution_intent(
        &self,
        intent: &ExecutionIntentInsert,
    ) -> anyhow::Result<ExecutionIntentRow> {
        let chain_id = i32::try_from(intent.chain_id)
            .with_context(|| format!("Chain ID {} exceeds PostgreSQL INTEGER", intent.chain_id))?;
        let created_block = i64::try_from(intent.created_block).with_context(|| {
            format!(
                "Execution creation block {} exceeds PostgreSQL BIGINT",

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Re-run the migration - every statement is idempotent and the failed commit left the schema at v1
  2. Raise idle_in_transaction_session_timeout above the expected migration duration
  3. Run migrations over a direct connection rather than a transaction-pooling proxy
Defensive patterns

Strategy: retry

Try / catch

match db.ensure_execution_transaction_schema().await {
    Err(e) if e.downcast_ref::<sqlx::Error>().is_some_and(|se| matches!(se, sqlx::Error::Io(_) | sqlx::Error::ConnectionClosed(_))) => {
        // commit failed: schema rolled back to v1; re-run the idempotent migration after connectivity returns
    }
    other => other?,
}

Prevention

When it happens

Trigger: Connection reset after the DDL ran but before COMMIT; Postgres crash or failover mid-migration; idle_in_transaction_session_timeout expiring during a long migration.

Common situations: Unstable links to managed databases; long migrations on big tables colliding with idle timeouts; transaction-pooling proxies in the path.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/6ce57d9c96b10fc1. Report an issue: GitHub.