nautechsystems/nautilus_trader · error

Payload operation batch size must be between 1 and {MAX_PAYL

Error message

Payload operation batch size must be between 1 and {MAX_PAYLOAD_OPERATION_BATCH_SIZE}

What it means

`validate_payload_operation_batch_size` enforces that the caller-supplied payload operation batch size is within [1, MAX_PAYLOAD_OPERATION_BATCH_SIZE] before converting it to i64. Values of 0 or above the maximum are rejected since the batch protocol requires a bounded, positive batch size.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:3590

fn replacement_scan_range(from_block: u64, head_block: u64) -> anyhow::Result<RangeInclusive<u64>> {
    anyhow::ensure!(
        head_block >= from_block,
        "Canonical head {head_block} is behind execution creation block {from_block}"
    );
    let max_end = from_block.saturating_add(MAX_REPLACEMENT_SCAN_BLOCKS - 1);
    Ok(from_block..=head_block.min(max_end))
}

fn current_unix_secs() -> anyhow::Result<u64> {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map_err(|_| anyhow::anyhow!("Trusted host clock precedes the Unix epoch"))
        .map(|duration| duration.as_secs())
}

fn validate_payload_operation_batch_size(batch_size: usize) -> anyhow::Result<i64> {
    anyhow::ensure!(
        (1..=MAX_PAYLOAD_OPERATION_BATCH_SIZE).contains(&batch_size),
        "Payload operation batch size must be between 1 and {MAX_PAYLOAD_OPERATION_BATCH_SIZE}"
    );
    Ok(i64::try_from(batch_size).expect("bounded payload batch size fits i64"))
}

fn current_execution_hash(
    intent_id: i64,
    hashes: &[ExecutionTransactionHashRow],
) -> anyhow::Result<&ExecutionTransactionHashRow> {
    let mut current = hashes.iter().filter(|row| row.current);
    let row = current
        .next()
        .ok_or_else(|| anyhow::anyhow!("Execution intent {intent_id} has no current hash"))?;
    anyhow::ensure!(
        current.next().is_none(),
        "Execution intent {intent_id} has more than one current hash"
    );

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set the batch size to a value between 1 and MAX_PAYLOAD_OPERATION_BATCH_SIZE (check the constant for the current limit).
  2. Clamp or validate the configured value at config-load time.
  3. If a larger batch is genuinely needed, raise the constant in code rather than passing an out-of-range runtime value.

Example fix

// before
payload_batch_size = 0
// after
payload_batch_size = 50  // 1 <= n <= MAX_PAYLOAD_OPERATION_BATCH_SIZE
Defensive patterns

Strategy: validation

Validate before calling

const MAX: usize = MAX_PAYLOAD_OPERATION_BATCH_SIZE as usize;
anyhow::ensure!((1..=MAX).contains(&batch_size), "batch_size {batch_size} outside 1..={MAX}");

Try / catch

match validate_payload_operation_batch_size(cfg.batch_size) {
    Err(_) => use_default_batch_size(),
    Ok(size) => submit_with_batch_size(size),
}

Prevention

When it happens

Trigger: Configuring or calling payload operation submission with `batch_size = 0` or `batch_size > MAX_PAYLOAD_OPERATION_BATCH_SIZE` — e.g. a config file with `payload_batch_size: 0`, or a user trying to 'send everything at once' with an oversized value.

Common situations: Zero interpreted as 'unlimited' by users; copy-pasting a batch size from another adapter with a different maximum; environment variable parsed into 0 on malformed input.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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