nautechsystems/nautilus_trader · error

Lighter position snapshot does not cover the requested instr

Error message

Lighter position snapshot does not cover the requested instrument scope

What it means

generate_position_status_reports builds position reports from a cached Lighter snapshot and a completeness flag. When the snapshot only covered part of the requested instrument scope (complete == false), the method refuses to return partial data presented as a full reconciliation and fails with this ensure!. It protects reconciliation from treating an incomplete exchange snapshot as authoritative.

Source

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

        Self::log_report_receipt(reports.len(), "OrderStatusReport", cmd.log_receipt_level);
        Ok(reports)
    }

    async fn generate_fill_reports(
        &self,
        cmd: GenerateFillReports,
    ) -> anyhow::Result<Vec<FillReport>> {
        let reports = self.paginate_fill_reports(&cmd).await?.reports;
        Self::log_report_receipt(reports.len(), "FillReport", cmd.log_receipt_level);
        Ok(reports)
    }

    async fn generate_position_status_reports(
        &self,
        cmd: &GeneratePositionStatusReports,
    ) -> anyhow::Result<Vec<PositionStatusReport>> {
        let (reports, complete, _) = self.cached_position_reports(cmd)?;
        anyhow::ensure!(
            complete,
            "Lighter position snapshot does not cover the requested instrument scope",
        );
        Self::log_report_receipt(reports.len(), "PositionStatusReport", cmd.log_receipt_level);
        Ok(reports)
    }

    async fn generate_mass_status(
        &self,
        lookback_mins: Option<u64>,
    ) -> anyhow::Result<Option<ExecutionMassStatus>> {
        let ts_init = self.clock.get_time_ns();

        // Scope inactive orders at the venue and stop descending trade
        // pagination once it crosses this local lookback boundary.
        let lookback_start = lookback_mins
            .map(DurationNanos::try_from_mins)
            .transpose()?

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Retry generate_position_status_reports after the Lighter position snapshot refreshes to full coverage.
  2. Check which instruments were skipped in the snapshot fetch (logs around snapshot_positions_with_coverage) and ensure those markets are registered in the registry.
  3. If a specific instrument is intended, call the per-instrument path (cmd.instrument_id set) instead of requesting the full scope.
  4. Verify network/API stability to Lighter; partial snapshots are usually caused by failed or truncated pages.

Example fix

// before
let (reports, complete, _) = self.cached_position_reports(cmd)?;
anyhow::ensure!(complete, "Lighter position snapshot does not cover the requested instrument scope");
// after
let (reports, complete, _) = self.cached_position_reports(cmd)?;
if !complete {
    // wait for a fresh full snapshot instead of failing immediately
    self.refresh_position_snapshot().await?;
    let (reports, complete, _) = self.cached_position_reports(cmd)?;
    anyhow::ensure!(complete, "Lighter position snapshot does not cover the requested instrument scope");
    return Ok(reports);
}
Defensive patterns

Strategy: retry

Validate before calling

let (reports, complete, _) = cached_position_reports(cmd)?;
if !complete { /* defer or retry */ }

Type guard

fn snapshot_is_complete(coverage: &Option<Coverage>) -> bool { coverage.as_ref().map(|c| c.is_complete()).unwrap_or(false) }

Try / catch

match client.generate_position_status_reports(cmd).await {
    Ok(reports) => process(reports),
    Err(e) if e.to_string().contains("does not cover the requested instrument scope") => schedule_retry(e),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling generate_position_status_reports (mass status / reconciliation) when the cached position snapshot was marked incomplete — e.g. a paginated or partial Lighter position fetch that did not cover every instrument in scope, or a previous per-instrument query that skipped rows so the retained cache is only explicitly incomplete mass-status data.

Common situations: Lighter API returning partial position pages during reconnect, snapshots taken while instruments are still being registered in the registry, or reconciliation running immediately after startup before a full position snapshot has been cached.

Related errors


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