nautechsystems/nautilus_trader · error · anyhow::Error

Execution payload migration found {invalid} invalid represen

Error message

Execution payload migration found {invalid} invalid representation(s)

What it means

After migrating execution payload representations, this check counts rows whose stored representation (raw_transaction / sealed_transaction presence) contradicts the expected payload state, and aborts the migration if any are invalid. It guards against the migration producing an inconsistent mix of legacy and protected representations.

Source

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

    async fn complete_execution_payload_migration(
        &self,
        transaction: &mut Transaction<'_, Postgres>,
        keys: &PayloadKeySet,
    ) -> anyhow::Result<()> {
        sqlx::query("LOCK TABLE execution_transaction_hash IN SHARE ROW EXCLUSIVE MODE")
            .execute(&mut **transaction)
            .await
            .context("failed to lock execution payload migration completion")?;
        let invalid = sqlx::query_scalar::<_, i64>(
            "SELECT COUNT(*) FROM execution_transaction_hash \
             WHERE (payload_expected AND (raw_transaction IS NOT NULL OR sealed_transaction IS NULL)) \
                OR (NOT payload_expected AND (raw_transaction IS NOT NULL OR sealed_transaction IS NOT NULL))",
        )
        .fetch_one(&mut **transaction)
        .await
        .context("failed to verify migrated execution payload representations")?;
        anyhow::ensure!(
            invalid == 0,
            "Execution payload migration found {invalid} invalid representation(s)"
        );
        validate_execution_payload_key_inventory(transaction, keys).await?;

        for statement in [
            "ALTER TABLE execution_transaction_hash \
             DROP CONSTRAINT IF EXISTS execution_transaction_payload_protected_check",
            "ALTER TABLE execution_transaction_hash \
             ADD CONSTRAINT execution_transaction_payload_protected_check CHECK ( \
                 (payload_expected AND raw_transaction IS NULL AND sealed_transaction IS NOT NULL) \
                 OR (NOT payload_expected AND raw_transaction IS NULL AND sealed_transaction IS NULL) \
             )",
        ] {
            sqlx::query(statement)
                .execute(&mut **transaction)
                .await
                .context("failed to install protected execution payload constraint")?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Identify the offending rows with the migration's verification query and fix them manually to match payload_expected
  2. Restore the tables from a backup taken before the failed migration
  3. Re-run migration from a clean pre-migration state
  4. Check application code that writes raw_transaction/sealed_transaction directly, bypassing the migration invariants
Defensive patterns

Strategy: validation

Validate before calling

let invalid: i64 = sqlx::query_scalar(
    "SELECT COUNT(*) FROM execution_payload_state s JOIN execution_payload p ON ... WHERE (s.payload_expected AND (p.raw_transaction IS NOT NULL OR p.sealed_transaction IS NULL)) OR (NOT s.payload_expected AND (p.raw_transaction IS NOT NULL OR p.sealed_transaction IS NOT NULL))"
).fetch_one(&mut conn).await?;
assert_eq!(invalid, 0, "fix invalid payload representations before migrating");

Prevention

When it happens

Trigger: Running the execution payload migration when rows exist where payload_expected is true but sealed_transaction is NULL or raw_transaction leaked in, or payload_expected is false but transaction columns are populated.

Common situations: Interrupted earlier migration leaving half-migrated rows; manual edits to execution payload tables; schema changes that bypassed the migration's invariants.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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