nautechsystems/nautilus_trader · error

Execution intent has no current hash

Error message

Execution intent {intent_id} has no current hash

What it means

When resolving the active transaction hash for an execution intent, the client filters hash rows to those flagged `current` and requires exactly one. This error means no row is marked current, so there is no canonical hash to track the intent's on-chain transaction (after replacements there must always be one designated live hash).

Solutions

  1. Inspect `execution_transaction_hash` rows for the intent and check the `current` flags.
  2. Repair by marking the latest/live hash row as current (single row) inside one transaction.
  3. Re-run the replacement flow if state is ambiguous, or restore consistent ledger state from a known-good point.

Example fix

// before: crash left no current row
UPDATE execution_transaction_hash SET current = false WHERE intent_id = 42; -- crashed before next UPDATE
// after: single transaction flips flags atomically
BEGIN; UPDATE ... SET current=false ...; UPDATE ... SET current=true WHERE hash=$new; COMMIT;
Defensive patterns

Strategy: validation

Validate before calling

let current_rows: Vec<_> = hashes.iter().filter(|r| r.current).collect();
anyhow::ensure!(current_rows.len() == 1, "intent {} has {} current hashes", intent_id, current_rows.len());

Try / catch

match select_current_hash_row(intent_id, &hashes) {
    Err(e) if e.to_string().contains("has no current hash") => repair_current_flag(intent_id).await,
    other => other,
}

Prevention

When it happens

Trigger: Looking up the current hash for `intent_id` when the hash table contains rows for the intent but none has `current = true` — e.g. a replacement transition that cleared the old current flag but failed to set the new one, or manual DB edits.

Common situations: Interrupted replacement flow (crash between flag updates); migration/backfill that dropped the current flags; concurrent writers racing on the current-flag update.

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/a9295e08391d8928. Report an issue: GitHub.

Appendix: source

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

        .map(|duration| duration.as_secs())
}

fn validate_payload_operation_batch_size(batch_size: usize) -> anyhow::Result<i64> {
    anyhow::ensure!(
        (1..=MAX_PAYLOAD_OPERATION_BATCH_SIZE).contains(&batch_size),
        "Payload operation batch size must be between 1 and {MAX_PAYLOAD_OPERATION_BATCH_SIZE}"
    );
    Ok(i64::try_from(batch_size).expect("bounded payload batch size fits i64"))
}

fn current_execution_hash(
    intent_id: i64,
    hashes: &[ExecutionTransactionHashRow],
) -> anyhow::Result<&ExecutionTransactionHashRow> {
    let mut current = hashes.iter().filter(|row| row.current);
    let row = current
        .next()
        .ok_or_else(|| anyhow::anyhow!("Execution intent {intent_id} has no current hash"))?;
    anyhow::ensure!(
        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

View on GitHub (pinned to 18893faf8b)