nautechsystems/nautilus_trader · error · anyhow::Error

Execution payload batch size must be positive

Error message

Execution payload batch size must be positive

What it means

migrate_execution_payload_batch validates its batch_size parameter before opening a transaction. Migration proceeds in bounded batches, so a non-positive batch size is a caller programming error rejected up front with anyhow::ensure!.

Source

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

             ON CONFLICT (key_id) DO NOTHING",
        )
        .bind(keys.active_key_id().as_slice())
        .execute(&mut *transaction)
        .await
        .context("failed to initialize execution payload key state")?;
        transaction
            .commit()
            .await
            .context("failed to commit execution payload activation")?;
        Ok(())
    }

    async fn migrate_execution_payload_batch(
        &self,
        keys: &PayloadKeySet,
        batch_size: i64,
    ) -> anyhow::Result<bool> {
        anyhow::ensure!(
            batch_size > 0,
            "Execution payload batch size must be positive"
        );
        let mut transaction = self
            .pool
            .begin()
            .await
            .context("failed to start execution payload migration batch")?;
        lock_execution_payload_operation(&mut transaction).await?;
        let state_row = sqlx::query(
            "SELECT deployment_id, protocol_version, operation, active_key_id \
             FROM execution_payload_state WHERE component = 'signed_transactions' FOR UPDATE",
        )
        .fetch_optional(&mut *transaction)
        .await
        .context("failed to lock execution payload migration state")?
        .ok_or_else(|| anyhow::anyhow!("Execution payload migration state is missing"))?;
        let state = execution_payload_state_from_row(&state_row)?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass a positive batch size (>= 1); clamp or validate the value at the call site
  2. Fix the config/source supplying batch_size so it cannot be zero or negative
  3. Use .max(1) or a checked computation when deriving batch_size from counters

Example fix

// before
let migrated = db.migrate_execution_payload_batch(&keys, batch_size).await?;
// after
let batch_size = batch_size.max(1);
let migrated = db.migrate_execution_payload_batch(&keys, batch_size).await?;
Defensive patterns

Strategy: validation

Validate before calling

fn validate_batch_size(batch_size: i64) -> Result<i64, String> {
    if batch_size > 0 { Ok(batch_size) } else { Err(format!("batch_size must be positive, got {batch_size}")) }
}

Type guard

fn is_positive_batch(n: i64) -> bool { n > 0 }

Try / catch

let batch_size = validate_batch_size(cfg.migrate_batch_size).map_err(anyhow::Error::msg)?;
let done = db.migrate_execution_payload_batch(&keys, batch_size).await?;

Prevention

When it happens

Trigger: Calling migrate_execution_payload_batch with batch_size <= 0 (e.g. 0, or a negative value from a misparsed config or an integer underflow when computing remaining work).

Common situations: Config file with migrate_batch_size: 0; computing batch_size as remaining - processed when remaining <= processed; wiring a signed value from the wrong source.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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