nautechsystems/nautilus_trader · error · anyhow::Error

Failed to lock legacy execution transactions: {e}

Error message

Failed to lock legacy execution transactions: {e}

What it means

Thrown when the LOCK TABLE execution_transaction IN ACCESS EXCLUSIVE MODE statement inside ensure_execution_transaction_schema fails. This exclusive lock fences older writers during the v2 migration; the wrapped error typically reports 'lock timeout', 'deadlock detected', 'relation "execution_transaction" does not exist', or a privilege failure. No DDL has run when this fires.

Source

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

    /// The migration locks the legacy transaction table, refuses unresolved version 1 rows,
    /// installs the versioned intent and hash-history tables, and fences older writers before
    /// releasing the lock. This prevents a mixed-version process from bypassing the new signer
    /// ownership constraints.
    ///
    /// # Errors
    ///
    /// Returns an error if the database operation fails.
    pub async fn ensure_execution_transaction_schema(&self) -> anyhow::Result<()> {
        let mut transaction = self
            .pool
            .begin()
            .await
            .map_err(|e| anyhow::anyhow!("Failed to start execution schema migration: {e}"))?;

        sqlx::query("LOCK TABLE execution_transaction IN ACCESS EXCLUSIVE MODE")
            .execute(&mut *transaction)
            .await
            .map_err(|e| anyhow::anyhow!("Failed to lock legacy execution transactions: {e}"))?;

        for statement in [
            "
            ALTER TABLE execution_transaction
            ADD COLUMN IF NOT EXISTS client_order_id TEXT
            ",
            "
            ALTER TABLE execution_transaction
            ADD COLUMN IF NOT EXISTS wallet_address TEXT
            ",
            "
            ALTER TABLE execution_transaction
            ALTER COLUMN wallet_address DROP NOT NULL
            ",
            "
            CREATE TABLE IF NOT EXISTS execution_schema_version (
                component TEXT PRIMARY KEY,
                version SMALLINT NOT NULL CHECK (version > 0)

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Read the appended {e}: 'relation does not exist' means the v1 table is missing - point at the correct database or create the legacy table first
  2. Stop all old-version processes before migrating so the exclusive lock is granted immediately
  3. Raise or clear lock_timeout/statement_timeout for the migration session
  4. If blocked, find blockers in pg_stat_activity and terminate them, then re-run (the migration is idempotent)
Defensive patterns

Strategy: retry

Validate before calling

-- Confirm the legacy table exists and see blockers before migrating
SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'execution_transaction');
SELECT pid, state, query FROM pg_stat_activity WHERE wait_event_type = 'Lock';

Try / catch

match db.ensure_execution_transaction_schema().await {
    Err(e) => {
        let msg = e.to_string();
        if msg.contains("lock timeout") || msg.contains("deadlock") {
            // retry after the blocking session finishes; migration is idempotent
        } else if msg.contains("does not exist") {
            // wrong database or missing v1 table - fix the target, do not retry
        } else {
            return Err(e);
        }
    }
    Ok(()) => {}
}

Prevention

When it happens

Trigger: Running the v2 migration while an old-version node still holds locks on execution_transaction; session lock_timeout/statement_timeout aborts the ACCESS EXCLUSIVE wait; a fresh database where the legacy v1 execution_transaction table was never created; role lacks privileges on the table.

Common situations: Rolling upgrade where old and new binaries overlap against one database; DBA-set lock_timeout; pointing the node at an empty database instead of the evolved one.

Related errors


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