nautechsystems/nautilus_trader · error

Signed transaction payload nonce is invalid

Error message

Signed transaction payload nonce is invalid

What it means

Thrown in `unseal` when the nonce bytes parsed from the envelope are not a valid 12-byte AEAD nonce (Ring's `Nonce::try_assume_unique_for_key` rejects them). This indicates the envelope structure or its nonce field is malformed.

Source

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

        Ok(envelope)
    }

    pub(crate) fn unseal(
        &self,
        envelope: &[u8],
        context: &PayloadContext,
    ) -> anyhow::Result<Vec<u8>> {
        validate_context(context, &self.deployment_id)?;
        let parsed = parse_envelope(envelope)?;
        let key = self.keys.get(&parsed.key_id).ok_or_else(|| {
            anyhow::anyhow!(
                "Payload sealing key {} is not configured",
                hex::encode(parsed.key_id)
            )
        })?;
        let aad = encode_aad(&parsed.key_id, context)?;
        let nonce = Nonce::try_assume_unique_for_key(parsed.nonce)
            .map_err(|_| anyhow::anyhow!("Signed transaction payload nonce is invalid"))?;
        let mut plaintext = parsed.ciphertext_and_tag.to_vec();
        let plaintext_len = key
            .open_in_place(nonce, Aad::from(aad), &mut plaintext)
            .map_err(|_| anyhow::anyhow!("Signed transaction payload authentication failed"))?
            .len();
        plaintext.truncate(plaintext_len);
        anyhow::ensure!(
            plaintext.len() <= MAX_SIGNED_TRANSACTION_BYTES,
            "Unsealed transaction payload is {} bytes, exceeding the {} byte limit",
            plaintext.len(),
            MAX_SIGNED_TRANSACTION_BYTES
        );
        Ok(plaintext)
    }
}

pub(crate) fn authenticate_payload(
    raw_transaction: &[u8],

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the envelope is intact (correct total length: header + key id + nonce + ciphertext+tag) and re-copy from source if corrupted
  2. Confirm the envelope version byte matches the parser version in use
  3. Re-seal and persist the payload from its original source if the stored envelope is unrecoverable
Defensive patterns

Strategy: validation

Validate before calling

// envelope layout: version(1) + key_id + nonce(12) + ciphertext_and_tag
if envelope.len() < ENVELOPE_HEADER_LEN {
    return Err(anyhow!("envelope truncated"));
}

Type guard

fn envelope_well_formed(e: &[u8]) -> bool { e.len() >= ENVELOPE_HEADER_LEN }

Try / catch

match sealer.unseal(&envelope, &ctx) {
    Err(e) if e.to_string().contains("nonce is invalid") => {
        restore_envelope_from_backup().context("envelope corrupted")?
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling `unseal` with an envelope whose 12-byte nonce region was truncated, corrupted, or produced by a different envelope version/parser.

Common situations: Manual envelope editing, storage-layer truncation, byte-offset drift after a format change, or copying payloads between systems with encoding corruption.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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