nautechsystems/nautilus_trader · error

failed to parse matching Lighter order {} for market_index={

Error message

failed to parse matching Lighter order {} for market_index={market_index}

What it means

A venue order matching the lookup criteria was found, but parse_http_order_to_report could not convert it into an OrderStatusReport (instrument mapping or field validation failed). The lookup aborts instead of returning a malformed report.

Source

Thrown at crates/adapters/lighter/src/websocket/dispatch.rs:1851

    let auth = mint_auth_token(credential)?;
    let query = Zeroizing::new(LighterAccountActiveOrdersQuery {
        authorization: None,
        auth: Some(auth.clone()),
        account_index: credential.account_index(),
        market_id: market_index,
    });
    let active = http_client
        .get_account_active_orders(&query)
        .await
        .context("failed to fetch Lighter active orders")?;

    let ts_init = clock.get_time_ns();
    let supplied_cloid = client_order_id.copied();

    let finalize = |order: &LighterOrder| -> anyhow::Result<OrderStatusReport> {
        let report =
            parse_http_order_to_report(order, registry, account_id, ts_init).ok_or_else(|| {
                anyhow::anyhow!(
                    "failed to parse matching Lighter order {} for market_index={market_index}",
                    order.order_id,
                )
            })?;
        let mut report = dispatch.translate_order_cloid(report);
        // Substitute the caller-supplied cloid whenever it positively
        // identifies this order: when the order's
        // `client_order_index` equals the deterministic derivation from
        // `supplied_cloid`. This covers two cases the cloid_map cannot
        // serve after a fresh client instance:
        //   1. The match came via `client_order_index`.
        //   2. The match came via venue order id, but the caller also
        //      supplied the matching cloid.
        // Substituting on the derivation match (rather than which path
        // matched first) avoids leaving the venue numeric cloid on the
        // report whenever the supplied cloid is the right one.
        if let Some(cloid) = supplied_cloid
            && let Some(client_index) = target_client_index

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Confirm the matched order's market has a registered instrument before querying (load/refresh instruments).
  2. Capture the raw order payload in logs and update parse_http_order_to_report to accept the new shape.
  3. Restrict the query to markets in your configured instrument universe.

Example fix

// before: query against a market not in the registry
let report = lookup(..., market_index_not_loaded)?;
// after: guard first
anyhow::ensure!(registry.instrument_for_market(market_index).is_some(), "market {market_index} not registered");
Defensive patterns

Strategy: try-catch

Validate before calling

if registry.instrument_for_market(market_index).is_none() { skip; }

Try / catch

match lookup { Err(e) if e.to_string().contains("failed to parse matching Lighter order") => { /* refresh instruments, log raw order, retry */ }, r => r? }

Prevention

When it happens

Trigger: finalize() called on a matched LighterOrder whose market/instrument mapping or numeric fields fail parsing — e.g. matching order belongs to a market absent from the registry, or contains values the parser rejects.

Common situations: Reconciling orders on markets outside the configured instrument set; venue-side field changes (new order states/pricing) not yet handled by the parser; corrupted or partial order payloads.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/f09449a7fe704a07. Report an issue: GitHub.