nautechsystems/nautilus_trader · error · anyhow::Error

Failed to migrate execution_transaction table

Error message

Failed to migrate execution_transaction table: {e}

What it means

This error wraps failure executing one of the DDL migration statements (e.g. ALTER TABLE execution_transaction ADD COLUMN IF NOT EXISTS ...) inside the migration transaction. The library throws it to attribute the failure to the table migration step specifically.

Solutions

  1. Check the inner `{e}` for the failing statement and Postgres error code
  2. Verify the migration user has ALTER privileges on the table
  3. Inspect current column types via information_schema and reconcile with expected types
  4. Run migrations against a staging copy of the database first

Example fix

// before
.map_err(|e| anyhow::anyhow!("Failed to migrate execution_transaction table: {e}"))?;
// after
.map_err(|e| {
    tracing::error!(error = %e, statement, "execution_transaction DDL failed");
    anyhow::anyhow!("Failed to migrate execution_transaction table: {e}")
})?;
Defensive patterns

Strategy: try-catch

Validate before calling

let can_alter = sqlx::query_scalar::<_, bool>(
    "SELECT has_table_privilege(current_user, 'execution_transaction', 'ALTER')"
).fetch_one(&pool).await?;
if !can_alter { anyhow::bail!("migration user lacks ALTER privilege on execution_transaction"); }

Try / catch

match ensure_execution_transaction_schema().await {
    Ok(()) => (),
    Err(e) if e.to_string().contains("Failed to migrate") => {
        inspect_column_types(&pool).await?; // diagnose via information_schema
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Executing the migration statements when a column already exists with an incompatible type, insufficient privileges for ALTER TABLE, the lock was lost (statement trigger on a different table), or syntax/type errors in a statement for the target Postgres version.

Common situations: Running with a DB user lacking DDL privileges; mixed schema versions where a column exists as a different type; older Postgres versions not supporting IF NOT EXISTS variants.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/0df7b7191efe9a4f. Report an issue: GitHub.

Appendix: source

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

                from_status TEXT,
                to_status TEXT NOT NULL,
                block_number BIGINT,
                block_hash TEXT,
                observed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
                CHECK (block_number IS NULL OR block_number >= 0),
                CHECK (to_status IN (
                    'prepared', 'signed', 'broadcast', 'included', 'finalized',
                    'reverted', 'replaced', 'dropped', 'reorged', 'recoverable'
                )),
                UNIQUE (intent_id, transition_key)
            )
            ",
        ] {
            sqlx::query(statement)
                .execute(&mut *transaction)
                .await
                .map_err(|e| {
                    anyhow::anyhow!("Failed to migrate execution_transaction table: {e}")
                })?;
        }

        let installed_version = sqlx::query_scalar::<_, i16>(
            "SELECT version FROM execution_schema_version WHERE component = 'evm_execution'",
        )
        .fetch_optional(&mut *transaction)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to read execution schema version: {e}"))?;
        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
            );
        }

View on GitHub (pinned to 18893faf8b)