nautechsystems/nautilus_trader · error

failed to fetch Lighter fills

Error message

failed to fetch Lighter fills

What it means

When fetching fills (trade history) from Lighter via get_trades, a failed HTTP/API call is wrapped as 'failed to fetch Lighter fills'. The request parameters (market_id, account_index, cursor) are logged with auth scrubbed before this error is raised, so callers get pagination context plus the underlying cause.

Source

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

                trade_type: None,
                limit: LIGHTER_REST_PAGE_SIZE,
                aggregate: None,
            });

            let response = match self.http_client.get_trades(&query).await {
                Ok(response) => response,
                Err(e) => {
                    // `{e:#}` preserves the venue's status/body across the
                    // outer context wrap; `scrub_auth` redacts any `auth=`
                    // query value the HTTP layer's error included.
                    log::warn!(
                        "Lighter get_trades failed (market_id={:?}, account_index={}, cursor={:?}): {}",
                        query.market_id,
                        credential.account_index(),
                        cursor,
                        scrub_auth(&format!("{e:#}")),
                    );
                    return Err(anyhow::Error::new(e).context("failed to fetch Lighter fills"));
                }
            };

            for trade in &response.trades {
                let Some(instrument_id) = self.registry.instrument_id(trade.market_id) else {
                    anyhow::bail!(
                        "no Lighter instrument registered for fill market_index={}",
                        trade.market_id,
                    );
                };
                let Some(instrument) = self.core.cache().instrument(&instrument_id).cloned() else {
                    anyhow::bail!("Lighter fill instrument {instrument_id} missing from cache");
                };

                match parse_ws_fill_report(
                    trade,
                    credential.account_index(),
                    &instrument,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the scrubbed inner error ({e:#}) for the HTTP status and Lighter error code.
  2. Reset pagination and re-fetch from the first page if the cursor was stale/invalid.
  3. Refresh or re-verify Lighter API credentials; auth failures surface here.
  4. Retry with backoff on 429/5xx; fills fetch is safe to re-run since it is read-only.

Example fix

// before
let trades = http_client.get_trades(query).await?; // Err -> failed to fetch Lighter fills
// after
let trades = backoff(|| http_client.get_trades(reset_cursor_if_stale(query)).await).await?;
Defensive patterns

Strategy: retry

Validate before calling

// validate cursor and market id before fetching fills
assert!(query.market_id.is_some() || query.fetch_all);

Try / catch

match client.generate_order_status_reports(...).await {
    Err(e) if format!("{e:#}").contains("failed to fetch Lighter fills") => {
        // reset cursor to None and retry with backoff
    }
    r => r?,
}

Prevention

When it happens

Trigger: generate_order_status_reports / fill generation path calls the Lighter get_trades endpoint with a market_id/account_index/cursor and the request returns Err — network failure, 4xx/5xx, auth rejection, or rate limit.

Common situations: Backfilling fills after a disconnect, paging through fills with a stale or invalid cursor, expired Lighter API credentials, or venue API downtime during report reconciliation.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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