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
- Inspect `execution_transaction_hash` rows for the intent and check the `current` flags.
- Repair by marking the latest/live hash row as current (single row) inside one transaction.
- 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
- Update current-hash flags atomically in a single DB transaction
- Add a DB constraint/trigger enforcing exactly one current row per intent
- Reconcile current flags after crashes or migrations
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
- Execution intent cannot own canonical nonce
- Execution nonce does not match canonical nonce
- Execution payload migration state is missing
- Execution payload rollback state is missing
- Execution payload storage is in
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_hashView on GitHub (pinned to 18893faf8b)