nautechsystems/nautilus_trader · error

Payload intent ID {} is not positive

Error message

Payload intent ID {} is not positive

What it means

validate_context requires a positive (non-zero) intent_id in the PayloadContext. Zero is treated as an unset/placeholder intent id, which would let a sealed payload reference nothing meaningful, so seal/unseal reject it.

Source

Thrown at crates/adapters/blockchain/src/execution/sealing.rs:435

    let key_id = envelope[1..1 + KEY_ID_LEN]
        .try_into()
        .expect("fixed key ID slice length");
    let nonce_start = 1 + KEY_ID_LEN;
    let ciphertext_start = nonce_start + NONCE_LEN;
    Ok(ParsedEnvelope {
        key_id,
        nonce: &envelope[nonce_start..ciphertext_start],
        ciphertext_and_tag: &envelope[ciphertext_start..],
    })
}

fn validate_context(context: &PayloadContext, deployment_id: &str) -> anyhow::Result<()> {
    anyhow::ensure!(
        context.deployment_id == deployment_id,
        "Payload deployment ID does not match the configured key set"
    );
    anyhow::ensure!(
        context.intent_id > 0,
        "Payload intent ID {} is not positive",
        context.intent_id
    );
    Ok(())
}

fn encode_aad(key_id: &[u8; KEY_ID_LEN], context: &PayloadContext) -> anyhow::Result<Vec<u8>> {
    let mut aad = Vec::with_capacity(
        AAD_DOMAIN.len()
            + context.deployment_id.len()
            + 20
            + 32
            + KEY_ID_LEN
            + 9 * size_of::<u32>(),
    );
    append_aad_field(&mut aad, AAD_DOMAIN)?;
    append_aad_field(&mut aad, &[ENVELOPE_VERSION])?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Populate intent_id from the actual intent record before constructing PayloadContext
  2. Add a check/validation at the source (DB read or API response) that intent_id > 0
  3. Find where the zero default came from — likely an unfilled struct field — and make intent_id construction explicit

Example fix

// before
let ctx = PayloadContext { deployment_id: dep.to_string(), intent_id: 0, .. };
seal(&ctx, ...)?;
// after
let ctx = PayloadContext { deployment_id: dep.to_string(), intent_id: intent.id, .. };
anyhow::ensure!(ctx.intent_id > 0, "intent_id must be positive");
seal(&ctx, ...)?;
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_positive_intent_id(context: &PayloadContext) -> anyhow::Result<()> {
    anyhow::ensure!(context.intent_id > 0, "intent_id must be > 0, got {}", context.intent_id);
    Ok(())
}

Type guard

fn has_valid_intent_id(context: &PayloadContext) -> bool {
    context.intent_id > 0
}

Try / catch

match seal(&context, payload, deployment_id) {
    Ok(sealed) => sealed,
    Err(e) if e.to_string().contains("not positive") => {
        // load the real intent record before retrying
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling seal() or unseal() with a PayloadContext constructed with intent_id: 0 — typically a default-initialized struct or an intent id field that was never populated from the database record.

Common situations: PayloadContext built with Default::default() and only some fields filled; a DB row where intent_id was NULL/default; deserialization of a context from a source that omitted the intent id.

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/8df21280cefe6531. Report an issue: GitHub.