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
- Verify the envelope is intact (correct total length: header + key id + nonce + ciphertext+tag) and re-copy from source if corrupted
- Confirm the envelope version byte matches the parser version in use
- 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
- Store envelopes as opaque blobs; never parse or rewrite their bytes
- Include integrity checksums for envelopes in external storage
- Verify envelope lengths after any storage migration
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
- Canonical head changed during signer-nonce replacement scan
- Verified finalized transaction count advanced without an act
- Execution intent {} has a signed transaction {} that was not
- Canonical nonce advanced without an authenticated signer tra
- failed to allocate Lighter nonce: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/bb7fd09734773c2e.
Report an issue: GitHub.