nautechsystems/nautilus_trader · error

Persisted transaction row references intent {}, expected {}

Error message

Persisted transaction row references intent {}, expected {}

What it means

Thrown by `payload_context` when the persisted transaction-hash row's `intent_id` does not match the given intent row's `id`. This cross-row consistency check prevents building a payload context from mismatched database rows, which would produce a wrong AAD and fail authentication downstream.

Source

Thrown at crates/adapters/blockchain/src/execution/sealing.rs:337

            to,
            value,
            input,
            gas_limit: policy.gas_limit,
            max_fee_per_gas: policy.max_fee_per_gas,
        },
    )
}

fn persisted_signer(intent: &ExecutionIntentRow) -> anyhow::Result<Address> {
    Address::from_str(&intent.wallet_address).context("persisted execution wallet is invalid")
}

pub(crate) fn payload_context(
    intent: &ExecutionIntentRow,
    hash: &ExecutionTransactionHashRow,
    deployment_id: &str,
) -> anyhow::Result<PayloadContext> {
    anyhow::ensure!(
        hash.intent_id == intent.id,
        "Persisted transaction row references intent {}, expected {}",
        hash.intent_id,
        intent.id
    );
    payload_context_identity(intent, &hash.transaction_hash, hash.chain_id, deployment_id)
}

pub(crate) fn payload_context_identity(
    intent: &ExecutionIntentRow,
    transaction_hash: &str,
    row_chain_id: u32,
    deployment_id: &str,
) -> anyhow::Result<PayloadContext> {
    let nonce = intent
        .nonce
        .ok_or_else(|| anyhow::anyhow!("Execution intent {} has no signer nonce", intent.id))?;
    let transaction_hash = B256::from_str(transaction_hash).with_context(|| {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Fetch the hash row by the same intent ID used for the intent row (e.g. a keyed lookup rather than a broad query)
  2. Check for stale/duplicate transaction rows referencing old intent IDs and clean them up
  3. Verify ordering in concurrent code so the hash row is read after the intent row is finalized

Example fix

// before
let hash = store.get_hash_by_tx(tx_hash)?;
let ctx = payload_context(&intent, &hash, deployment_id)?;
// after
let hash = store.get_hash_for_intent(intent.id)?;
let ctx = payload_context(&intent, &hash, deployment_id)?;
Defensive patterns

Strategy: validation

Validate before calling

ensure!(hash_row.intent_id == intent_row.id, "mismatched hash/intent rows");
let ctx = payload_context(&intent_row, &hash_row, deployment_id)?;

Try / catch

let ctx = payload_context(&intent_row, &hash_row, DEPLOYMENT_ID)
    .context("hash/intent row mismatch; refetch rows by intent_id")?;

Prevention

When it happens

Trigger: Calling `payload_context` (directly or via open/rewrap/rollback/inspect execution payload functions) with a transaction hash row fetched for a different intent than the one passed in.

Common situations: Queries that join or fetch rows by non-intent keys and pass mismatched pairs, stale rows after intent re-creation (new ID but reused transaction row), or race conditions during concurrent intent processing.

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