nautechsystems/nautilus_trader · error

Lighter inactive-order lookup repeated cursor `{next}`

Error message

Lighter inactive-order lookup repeated cursor `{next}`

What it means

While paginating the inactive-orders endpoint, the adapter tracks seen cursors; if the venue returns a cursor it already followed, pagination would loop forever, so it fails fast. This detects a broken or non-advancing cursor from the API.

Source

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

            ask_filter: None,
            between_timestamps: None,
            cursor: cursor.clone(),
            limit: LIGHTER_REST_PAGE_SIZE,
        });
        let inactive = http_client
            .get_account_inactive_orders(&query)
            .await
            .context("failed to fetch Lighter inactive orders")?;

        for order in &inactive.orders {
            if matches_order(order) {
                return finalize(order).map(Some);
            }
        }

        match inactive.next_cursor {
            Some(next) if !next.is_empty() => {
                anyhow::ensure!(
                    seen_cursors.insert(next.clone()),
                    "Lighter inactive-order lookup repeated cursor `{next}`",
                );
                cursor = Some(next);
            }
            _ => break,
        }
    }

    Ok(None)
}

fn order_matches_lookup(
    order_index: i64,
    client_order_index: i64,
    target_venue_index: Option<i64>,
    target_client_index: Option<i64>,
) -> bool {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Disable or bypass response caching (ensure no-cache headers) between the adapter and Lighter's API.
  2. Retry the lookup later; if reproducible, report the cursor-loop to Lighter support with the cursor value.
  3. Locate the order via direct REST query by order_index instead of cursor pagination.

Example fix

// before: trusting venue cursors blindly
cursor = Some(next);
// after: keep the guard, but detect looping and surface the cursor
anyhow::ensure!(seen_cursors.insert(next.clone()), "repeated cursor `{next}` — venue pagination not advancing");
Defensive patterns

Strategy: retry

Try / catch

match lookup { Err(e) if e.to_string().contains("repeated cursor") => { tokio::time::sleep(delay).await; retry_lookup(); }, r => r? }

Prevention

When it happens

Trigger: The inactive-orders response repeats a non-empty next_cursor that was already visited — venue API bug, proxy/response caching replaying the same page, or desynced pagination state.

Common situations: Caching proxies or rate-limited responses serving stale pages; venue-side pagination bugs during API upgrades; retry layers returning cached responses.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


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