nautechsystems/nautilus_trader · error

Retained signed intent {} has no current hash

Error message

Retained signed intent {} has no current hash

What it means

During execution-verification state migration, the client replays each retained signed intent and requires a `current` transaction record (the current hash/attempt) to be present. This error is thrown when an active, signed intent has a nonce but its `current` option is None, meaning the persisted state is missing the hash of the transaction the signature was produced for. The library throws it because it cannot verify or migrate a signed intent without knowing which transaction hash it refers to, so it fails loudly instead of silently dropping on-chain state.

Source

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

                    nonce: None,
                    transaction_hash: None,
                    terminal_status: None,
                    block_number: None,
                    block_hash: None,
                    receipt_success: None,
                    gas_used: None,
                    effective_gas_price: None,
                    recover_prepared: true,
                    decisions: vec![base_decision],
                });
                continue;
            }

            let nonce = intent.nonce.ok_or_else(|| {
                anyhow::anyhow!("Retained signed intent {} has no nonce", intent.id)
            })?;
            let current = current.ok_or_else(|| {
                anyhow::anyhow!("Retained signed intent {} has no current hash", intent.id)
            })?;
            let raw_transaction = authenticated.get(&current.id).ok_or_else(|| {
                anyhow::anyhow!(
                    "Retained signed intent {} has no authenticated current payload",
                    intent.id
                )
            })?;

            if intent.active && nonce == next_canonical_nonce {
                anyhow::ensure!(
                    !matches!(intent.status.as_str(), "finalized" | "reverted"),
                    "Active terminal intent conflicts with the canonical nonce ledger"
                );
                records.push(ExecutionVerificationMigrationRecord {
                    intent_id: intent.id,
                    nonce: Some(nonce),
                    transaction_hash: Some(current.transaction_hash.clone()),
                    terminal_status: None,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the persisted execution state for the intent id reported in the message and restore the missing current transaction record from a complete backup.
  2. Re-run state persistence from a consistent snapshot: stop the node, restore the latest intact state file/DB, and restart so migration sees the full intent+transaction pair.
  3. If the intent was never broadcast and its signature is unusable, remove or mark the intent as `recoverable`/`dropped` in the state store (which the migration path allows for nonterminal intents) before restarting.
  4. Check that you are not mixing state produced by different adapter versions; upgrade/downgrade consistently so the `current` hash field is always populated.

Example fix

// before (corrupt state row: intent persisted without current transaction)
{"id": "intent-42", "active": true, "nonce": 7}  // no current hash

// after (complete record restored from backup)
{"id": "intent-42", "active": true, "nonce": 7, "current": {"id": "tx-9", "transaction_hash": "0xabc..."}}
Defensive patterns

Strategy: validation

Validate before calling

fn validate_signed_intent(intent: &Intent, current: Option<&TxRecord>) -> Result<(), String> {
    if intent.active && intent.nonce.is_some() && current.is_none() {
        return Err(format!("intent {} is signed but missing current hash", intent.id));
    }
    Ok(())
}

Type guard

fn has_current(intent: &Intent) -> bool {
    intent.active && intent.nonce.is_some() && intent.current.is_some()
}

Prevention

When it happens

Trigger: Raised by the migration routine in `client.rs` (`ok_or_else` on `current.ok_or_else(...)`) when iterating retained intents where: intent.active is true, intent.nonce is Some, but the `current` transaction record for the intent is absent from the loaded persistence snapshot — e.g. a partially-written or hand-edited state store, a truncated write that stored the intent but not its current transaction row, or deserializing state saved by a version that did not persist the current hash.

Common situations: Crash or kill between persisting the intent and its transaction hash; restoring state from an old backup or downgraded node against a newer state schema; manual tampering with the execution state DB; copying intent rows without their joined transaction rows between environments.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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