nautechsystems/nautilus_trader · critical
Protected execution transaction {} contains plaintext
Error message
Protected execution transaction {} contains plaintext What it means
For payloads expected to be sealed (encrypted), the code enforces that `raw_transaction` is None — an unprotected plaintext transaction alongside sealed storage means confidentiality was violated. The library refuses to process a transaction that stores both a sealed envelope and a plaintext copy. This protects against accidentally broadcasting or logging sensitive signed transactions.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:3624
current.next().is_none(),
"Execution intent {intent_id} has more than one current hash"
);
Ok(row)
}
fn open_execution_payload(
keys: &PayloadKeySet,
policy: PayloadPolicy,
intent: &ExecutionIntentRow,
hash: &ExecutionTransactionHashRow,
reason: &str,
) -> anyhow::Result<Vec<u8>> {
anyhow::ensure!(
hash.payload_expected,
"Execution transaction {} has no signed payload",
hash.transaction_hash
);
anyhow::ensure!(
hash.raw_transaction.is_none(),
"Protected execution transaction {} contains plaintext",
hash.transaction_hash
);
let envelope = hash.sealed_transaction.as_deref().ok_or_else(|| {
anyhow::anyhow!(
"Protected execution transaction {} has no sealed payload",
hash.transaction_hash
)
})?;
let context = payload_context(intent, hash, keys.deployment_id())?;
let raw_transaction = keys.unseal(envelope, &context)?;
log::info!(
"Unsealed execution payload for intent {} transaction {} during {reason}",
intent.id,
hash.transaction_hash
);
authenticate_retained_payload(&raw_transaction, intent, hash, keys.deployment_id())?;View on GitHub (pinned to 18893faf8b)
Solutions
- Remove the plaintext raw_transaction from the row (null it) and rely solely on the sealed envelope.
- Find and fix the code path that populated raw_transaction under a sealed payload policy.
- Verify the deployment's payload policy/environment is consistently sealed mode end to end.
- Rotate any secrets that may have been exposed via the plaintext payload, and audit logs for leaked transactions.
Example fix
// before row.raw_transaction = Some(raw_signed_tx); row.sealed_transaction = Some(seal(raw_signed_tx, &context)?); // after: never keep both row.sealed_transaction = Some(seal(raw_signed_tx, &context)?); row.raw_transaction = None;
Defensive patterns
Strategy: validation
Validate before calling
if hash.sealed_transaction.is_some() && hash.raw_transaction.is_some() {
anyhow::bail!("tx {} stores plaintext alongside sealed envelope", hash.transaction_hash);
} Type guard
fn is_protected_clean(hash: &ExecutionTransactionHashRow) -> bool {
hash.sealed_transaction.is_some() && hash.raw_transaction.is_none()
} Prevention
- Never write raw_transaction in sealed-mode deployments; gate the field behind the payload policy type.
- Scrub raw payloads from debug/test paths before merging.
- Audit logs and storage for plaintext signed transactions; rotate keys if any leaked.
When it happens
Trigger: Calling the payload-resolution function with a hash row where the protection policy requires sealing but `raw_transaction` is populated with plaintext bytes.
Common situations: A code path that writes raw_transaction for debug/testing and forgot to null it; an environment or policy downgrade (sealed mode intended but sealing disabled); a migration that copied raw payloads into a sealed deployment; mixed-version writers where an older component still stores plaintext.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Execution payload {} contains plaintext during rewrap
- Payload protection requires an active payload key
- Execution payload storage is in {operation} maintenance; com
- Execution payload protection is active, but no payload key i
- Execution payload storage is in {operation} maintenance, not
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/47420a1bd27c1c29.
Report an issue: GitHub.