nautechsystems/nautilus_trader · error · anyhow::Error

Failed to inspect legacy execution transactions

Error message

Failed to inspect legacy execution transactions: {e}

What it means

This error wraps failure of the safety inspection query that counts unresolved legacy transactions (status IN ('pending','included','reverted')) before migrating the execution schema. The library must verify no unresolved version-1 transactions exist; failing to run this check aborts migration.

Solutions

  1. Confirm the execution_transaction table and status column exist before migration
  2. Check the inner `{e}` for the exact Postgres error and address it (table, column, privileges)
  3. If legacy rows are the concern, resolve pending/included/reverted transactions with the prior app version before migrating
  4. Restore the expected version-1 schema from backups or prior migration scripts

Example fix

// before
.map_err(|e| anyhow::anyhow!("Failed to inspect legacy execution transactions: {e}"))?;
// after
.map_err(|e| {
    tracing::error!(error = %e, "legacy execution transaction inspection failed");
    anyhow::anyhow!("Failed to inspect legacy execution transactions: {e}")
})?;
Defensive patterns

Strategy: validation

Validate before calling

let unresolved = sqlx::query_scalar::<_, i64>(
    "SELECT count(*) FROM execution_transaction WHERE status IN ('pending','included','reverted')"
).fetch_one(&pool).await?;
if unresolved > 0 { anyhow::bail!("resolve {unresolved} legacy transactions before migrating"); }

Try / catch

match db.ensure_execution_transaction_schema().await {
    Ok(()) => (),
    Err(e) if e.to_string().contains("Failed to inspect legacy") => {
        // check table/column existence, then retry after repair
        repair_legacy_table(&pool).await?;
        db.ensure_execution_transaction_schema().await?;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Running ensure_execution_transaction_schema when the execution_transaction table or status column does not exist yet, the connection fails mid-transaction, or the aggregate query (fetch_one) errors due to permissions or type issues.

Common situations: Migrating a database where the legacy table was dropped or renamed; partially applied migrations leaving the table without expected columns; DB user lacking SELECT privileges.

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/85fa0a748d0449ee. Report an issue: GitHub.

Appendix: source

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

        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_transaction

View on GitHub (pinned to 18893faf8b)