nautechsystems/nautilus_trader · error

Lighter transaction lookup returned client_order_index {} fo

Error message

Lighter transaction lookup returned client_order_index {} for acknowledged create {client_order_index}

What it means

After the transaction identity checks pass, validate_acked_create_tx parses the tx info JSON into AckedCreateTxInfo and asserts its client_order_index equals the client_order_index of the order being verified. This guards against an exchange-side race or bug where the matched create transaction carries a different client order index than the locally acknowledged one.

Source

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

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 {
    let left = left
        .strip_prefix("0x")
        .or_else(|| left.strip_prefix("0X"))
        .unwrap_or(left);
    let right = right
        .strip_prefix("0x")
        .or_else(|| right.strip_prefix("0X"))
        .unwrap_or(right);
    left.eq_ignore_ascii_case(right)
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Confirm the client_order_index used when signing the create tx equals the order's client_order_id-derived index and matches what was stored at acknowledgement
  2. Retry the lookup/parse after a delay in case info JSON was stale
  3. If the exchange returns a different index, re-submit the create with a fresh, correctly derived client_order_index and re-acknowledge

Example fix

// before
ensure!(info.client_order_index == client_order_index, ...);
// after
if info.client_order_index != client_order_index {
    log::warn!("create tx index {} != acked {}", info.client_order_index, client_order_index);
    return Err(...);
}
Defensive patterns

Strategy: validation

Validate before calling

if info.client_order_index != expected_client_order_index {
    return Err(anyhow!("create tx index mismatch"));
}

Prevention

When it happens

Trigger: The tx lookup matched the create identity (hash/type/account/key/nonce) but the decoded tx.info contains a client_order_index different from the order's acknowledged client_order_index — e.g. info parsed from a wrong transaction or the acknowledgement recorded the wrong index.

Common situations: Client order index conversion issues (i64 overflow/offset between local IDs and exchange IDs); submitting with a regenerated client_order_index after retry while the old acknowledgement record is reused; duplicate submits where the matched tx is a prior attempt.

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