nautechsystems/nautilus_trader · error

Replacement transaction {} unexpectedly retains signed bytes

Error message

Replacement transaction {} unexpectedly retains signed bytes

What it means

A transaction row flagged as a replacement (payload_expected == false) must not carry signed bytes; finding raw_transaction or sealed_transaction set means the persistence invariant is broken and rebroadcasting could conflict with a live replacement.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:1209

        let mut authenticated_payloads = HashMap::new();
        let mut current_payload = None;

        for hash in &hashes {
            anyhow::ensure!(
                hash.intent_id == intent.id,
                "Persisted transaction row references intent {}, expected {}",
                hash.intent_id,
                intent.id
            );
            anyhow::ensure!(
                hash.chain_id == self.chain.chain_id,
                "Persisted transaction row chain ID {} does not match configured chain ID {}",
                hash.chain_id,
                self.chain.chain_id
            );

            if !hash.payload_expected {
                anyhow::ensure!(
                    hash.raw_transaction.is_none() && hash.sealed_transaction.is_none(),
                    "Replacement transaction {} unexpectedly retains signed bytes",
                    hash.transaction_hash
                );
                continue;
            }
            let raw_transaction = open_execution_payload(
                self.payload_keys
                    .as_deref()
                    .expect("payload keys checked above"),
                policy,
                &intent,
                hash,
                "recovery",
            )
            .map_err(|e| {
                anyhow::anyhow!(
                    "Execution intent {} signed transaction {} failed authentication: {e}",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Null out raw_transaction/sealed_transaction on that replacement row after confirming it was never broadcast
  2. Remove the inconsistent row and let recovery re-derive the replacement
  3. Audit the replacement-signing code path to ensure it persists hashes without signed bytes
Defensive patterns

Strategy: validation

Validate before calling

for h in hashes {
    if !h.payload_expected && (h.raw_transaction.is_some() || h.sealed_transaction.is_some()) {
        // clean the replacement row before recovery
    }
}

Prevention

When it happens

Trigger: connect() -> reconcile_unresolved_execution(): for a row where hash.payload_expected is false, either raw_transaction or sealed_transaction is Some.

Common situations: Partial/corrupted write during replacement flow; DB rows edited by tooling; version mismatch where older writers stored bytes for replacement rows.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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