nautechsystems/nautilus_trader · error
Protected execution transaction {} has no sealed payload
Error message
Protected execution transaction {} has no sealed payload What it means
When a transaction row declares a protected (sealed) payload, the code requires `sealed_transaction` to hold the sealed envelope bytes. If the envelope is absent, unsealing is impossible and submission aborts. This is the counterpart of the plaintext check: protected rows must carry exactly a sealed payload.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:3630
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())?;
if retained_payload_requires_policy(intent, hash, policy)? {
authenticate_payload(&raw_transaction, intent, hash, policy, keys.deployment_id())
.with_context(|| {
format!(
"execution intent {} transaction {} violates current execution policy",
intent.id, hash.transaction_hashView on GitHub (pinned to 18893faf8b)
Solutions
- Re-run the sealing/signing step to regenerate the envelope and persist it into sealed_transaction.
- Check the KMS/sealing service availability and credentials if sealing failed upstream.
- Restore the missing envelope from the blob store/backup or rebuild the row by replaying the pipeline.
- If the transaction should not be sealed, correct payload_expected/sealing policy rather than fabricating an envelope.
Example fix
// before: row recorded before sealing finished store.record_hash(row)?; // sealed_transaction still None // after row.sealed_transaction = Some(sealing_service.seal(&signed_tx, &context)?); store.record_hash(row)?;
Defensive patterns
Strategy: validation
Validate before calling
if hash.payload_expected && hash.raw_transaction.is_none() && hash.sealed_transaction.as_deref().map_or(true, |s| s.is_empty()) {
anyhow::bail!("tx {} missing sealed envelope; re-seal before submission", hash.transaction_hash);
} Type guard
fn has_sealed_payload(hash: &ExecutionTransactionHashRow) -> bool {
hash.sealed_transaction.as_deref().map_or(false, |s| !s.is_empty())
} Try / catch
match resolve_payload(keys, policy, intent, hash, reason) {
Ok(bytes) => submit(bytes),
Err(e) if e.to_string().contains("no sealed payload") => reseed_and_reseal(intent, hash),
Err(e) => return Err(e),
} Prevention
- Persist the sealed envelope in the same transaction as the hash row.
- Ensure GC jobs never delete envelopes for live rows.
- Alert on KMS/sealing-service failures so envelopes aren't silently skipped.
When it happens
Trigger: Calling the payload-resolution function with a hash row where `payload_expected` is true, `raw_transaction` is None, but `sealed_transaction` is also None or empty — the sealed envelope was never persisted or was deleted.
Common situations: Crash between writing the hash row and persisting the sealed envelope; a cleanup/GC job that removed sealed blobs but not the rows; failed KMS/sealing-service call that was swallowed; restoring rows from a backup without the blob store.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 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
- No order, orderTrigger, or orderPriorExecution data in event
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/fbaa88f6e6806f8f.
Report an issue: GitHub.