nautechsystems/nautilus_trader · error · anyhow::Error
Protected execution transaction {} has no envelope
Error message
Protected execution transaction {} has no envelope What it means
In the protected load path, a row correctly has no plaintext, but its sealed_transaction column is NULL, so there is no envelope to unseal. The loader requires every protected row to carry an envelope and aborts with this anyhow error otherwise.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:5231
anyhow::ensure!(
hash.raw_transaction.is_none() && hash.sealed_transaction.is_none(),
"Replacement execution transaction {} retains signed bytes",
hash.id
);
continue;
}
original_rows += 1;
let intent = load_execution_intent(&mut transaction, hash.intent_id).await?;
let raw_transaction = if let (Some(keys), Some(deployment_id)) =
(keys, deployment_id.as_deref())
{
anyhow::ensure!(
hash.raw_transaction.is_none(),
"Protected execution transaction {} contains plaintext",
hash.id
);
let envelope = hash.sealed_transaction.as_deref().ok_or_else(|| {
anyhow::anyhow!(
"Protected execution transaction {} has no envelope",
hash.id
)
})?;
let key_id = envelope_key_id(envelope)?;
anyhow::ensure!(
keys.contains_key(&key_id),
"Execution transaction {} requires an unavailable payload key",
hash.id
);
key_ids.insert(alloy::hex::encode(key_id));
let context = payload_context(&intent, hash, deployment_id)?;
keys.unseal(envelope, &context)?
} else {
anyhow::ensure!(
hash.sealed_transaction.is_none(),
"Legacy execution transaction {} contains an envelope",
hash.idView on GitHub (pinned to 18893faf8b)
Solutions
- Locate the row by id and re-seal its payload from a source of truth (e.g. re-derive from the execution intent) using the rewrap tooling.
- Restore the affected rows from a database backup taken before the failed rewrap.
- Check application/writer logs around the time the row was written for a failed envelope-sealing step.
- If the row is legitimately payload-less, mark it payload_expected=false so it is handled by the replacement-row path.
Example fix
// Corrupt protected row
{ id: "0xdef", raw_transaction: null, sealed_transaction: null }
// after re-seal
{ id: "0xdef", raw_transaction: null, sealed_transaction: "0x<sealed envelope bytes>" } Defensive patterns
Strategy: validation
Validate before calling
-- Protected rows missing both payload forms SELECT id FROM execution_transactions WHERE raw_transaction IS NULL AND sealed_transaction IS NULL AND payload_expected = true;
Try / catch
let envelope = match row.sealed_transaction {
Some(env) => env,
None => return Err(anyhow!("row {} missing envelope; re-seal required", row.id)),
}; Prevention
- Write plaintext and sealed envelope atomically in one transaction during migration.
- Alert on rewrap batches that report partial row counts.
- Verify backups include sealed_transaction columns.
When it happens
Trigger: Loading execution transactions with keys and deployment_id active while a row has raw_transaction IS NULL and sealed_transaction IS NULL (both payload columns empty).
Common situations: A crash during the rewrap left a row half-migrated (plaintext deleted before the envelope was written); the sealing writer failed silently; rows restored from a partial backup.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- 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
- Execution payload storage is in {operation} maintenance, not
- Protected execution transaction {} contains plaintext
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9ae646b289b1132a.
Report an issue: GitHub.