nautechsystems/nautilus_trader · error

Lighter transaction lookup did not match acknowledged create

Error message

Lighter transaction lookup did not match acknowledged create identity

What it means

validate_acked_create_tx fetches a Lighter on-chain transaction by hash and asserts it matches the acknowledged create-order identity: tx hash, tx type CreateOrder, account_index, api_key_index, and nonce. Any mismatch in that combined ensure! means the exchange returned a transaction that is not the create submission this client acknowledged, so the lookup cannot be trusted to verify the order's on-chain state.

Source

Thrown at crates/adapters/lighter/src/execution.rs:3371

    #[serde(rename = "ClientOrderIndex")]
    client_order_index: i64,
}

#[derive(Default, Deserialize)]
struct AckedCreateEvent {
    #[serde(default, rename = "ae")]
    app_error: String,
}

fn validate_acked_create_tx(
    tx: &crate::http::models::LighterTx,
    account_index: i64,
    api_key_index: u8,
    client_order_index: i64,
    nonce: i64,
    tx_hash: &str,
) -> anyhow::Result<()> {
    anyhow::ensure!(
        tx_hash_matches(&tx.hash, tx_hash)
            && tx.tx_type == LighterTxType::CreateOrder as u8
            && tx.account_index == account_index
            && tx.api_key_index == api_key_index
            && tx.nonce == nonce,
        "Lighter transaction lookup did not match acknowledged create identity",
    );
    let info: AckedCreateTxInfo = serde_json::from_str(&tx.info)
        .context("failed to parse Lighter create transaction info")?;
    anyhow::ensure!(
        info.client_order_index == client_order_index,
        "Lighter transaction lookup returned client_order_index {} for acknowledged create {client_order_index}",
        info.client_order_index,
    );
    Ok(())
}

fn tx_hash_matches(left: &str, right: &str) -> bool {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the tx_hash stored at acknowledgement time exactly matches the one sent (same casing/0x form) before calling validate_acked_create_tx
  2. Re-check that account_index, api_key_index, and nonce used in the lookup are the same values used to sign and submit the create transaction
  3. Re-fetch the transaction after a short delay in case the node served stale/pre-ack data, then retry validation
  4. If nonce drift is the cause, re-sync the nonce from the exchange before the next submission

Example fix

// before
validate_acked_create_tx(..., stale_nonce, old_tx_hash)?;
// after
let nonce = self.current_nonce(account_index, api_key_index).await?;
validate_acked_create_tx(..., nonce, &ack.tx_hash)?;
Defensive patterns

Strategy: validation

Validate before calling

assert_eq!(ack.tx_hash, submitted.tx_hash);
assert_eq!(ack.account_index, config.account_index);
assert_eq!(ack.api_key_index, config.api_key_index);
assert_eq!(ack.nonce, submitted.nonce);

Prevention

When it happens

Trigger: After submitting a create order, the async verification looked up the tx by hash but the node returned a transaction with a different hash (case/prefix mismatch), a different tx_type, or one belonging to a different account_index / api_key_index / nonce than the locally tracked acknowledgement.

Common situations: Using a wrong api_key_index or stale nonce when resubmitting after reconnect; querying against a non-sticky RPC node that has not yet indexed the tx and returns a hash-normalized or different tx; replaying an old tx_hash after a restart while account/nonce state moved on.

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