nautechsystems/nautilus_trader · error · anyhow::Error

Failed to persist connect verification: {e}

Error message

Failed to persist connect verification: {e}

What it means

Thrown while persisting a connect-verification decision row into the `execution_verification_decision` table inside the execution verification schema migration transaction. The library wraps the underlying sqlx/Postgres error so callers get context about which migration step failed. The insert itself is idempotent-looking append-only evidence written once per (revision, decision index).

Source

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

                    NULL, NULL, 'connect', $1, $2, $3, $4, $5, $6, $7, $8,
                    'all_valid', $9, $10, 'verified', $11
                )
                ",
            )
            .bind(decision.read_class)
            .bind(height_start)
            .bind(height_end)
            .bind(bootstrap.manifest_version)
            .bind(bootstrap.manifest_digest)
            .bind(bootstrap.provider_ids)
            .bind(bootstrap.operator_ids)
            .bind(bootstrap.failure_domain_ids)
            .bind(&decision.normalized_value_digest)
            .bind(revision)
            .bind(transition_key)
            .execute(&mut *transaction)
            .await
            .map_err(|e| anyhow::anyhow!("Failed to persist connect verification: {e}"))?;
        }

        for statement in [
            "
            CREATE OR REPLACE FUNCTION execution_verification_append_only()
            RETURNS TRIGGER AS $$
            BEGIN
                RAISE EXCEPTION 'Execution verification evidence is append-only';
            END;
            $$ LANGUAGE plpgsql
            ",
            "DROP TRIGGER IF EXISTS execution_verification_decision_append_only \
             ON execution_verification_decision",
            "
            CREATE TRIGGER execution_verification_decision_append_only
            BEFORE UPDATE OR DELETE ON execution_verification_decision
            FOR EACH STATEMENT EXECUTE FUNCTION execution_verification_append_only()
            ",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the inner sqlx error in the message to identify the exact DB failure
  2. Run the schema migrations / check `execution_schema_version` to confirm the verification schema exists at the expected version
  3. Check for concurrent instances running the migration against the same database and ensure only one bootstrap at a time
  4. Verify Postgres connectivity and that the user has INSERT privileges on execution_verification_decision

Example fix

// before: connecting to a stale/partially migrated DB and hitting the error
Database::connect(pool).await?;
// after: verify schema version before bootstrapping
let version: Option<i16> = sqlx::query_scalar(
    "SELECT version FROM execution_schema_version WHERE component = 'evm_execution_verification'")
    .fetch_optional(&pool).await?;
assert!(version.is_none() || version == Some(VERIFICATION_SCHEMA_VERSION));
Defensive patterns

Strategy: try-catch

Validate before calling

let ok: bool = sqlx::query_scalar(
    "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'execution_verification_decision')")
    .fetch_one(&pool).await?;
if !ok { run_table_migration_first()?; }

Try / catch

match ensure_verification_schema(&db).await {
    Err(e) if e.to_string().contains("Failed to persist connect verification") => {
        log::error!("verification write failed: {e:#}"); // inspect root-cause chain, check schema/privileges, retry bootstrap
    }
    Err(e) => return Err(e),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: `ensure_execution_verification_schema` runs during database bootstrap and any of the per-decision INSERTs fails: schema/table missing, column type mismatch (e.g. height exceeding BIGINT already rejected earlier, but digest/manifest type mismatch possible), constraint violation on transition_key (duplicate revision), or connection dropped mid-transaction.

Common situations: Upgrading an older database where the table schema predates a new column; a concurrent migration running on the same database causing unique violations on transition_key; network interruption between app and Postgres during startup; running against a non-Postgres or partially migrated database.

Related errors


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