nautechsystems/nautilus_trader · error · anyhow::Error

Either contracts or instrument_ids must be provided

Error message

Either contracts or instrument_ids must be provided

What it means

request_bars requires at least one way to identify the instruments to fetch: a list of IB Contract objects or a list of Nautilus InstrumentIds. If both are absent or empty, no history request could be formed, so the client bails.

Source

Thrown at crates/adapters/interactive_brokers/src/historical/client.rs:256

        }

        if let Some(start) = start_date_time
            && start >= end_date_time
        {
            anyhow::bail!("Start date must be before end date");
        }

        if let Some(duration) = duration {
            duration.parse::<historical::Duration>().with_context(|| {
                format!("duration must be in format: 'int S|D|W|M|Y', was '{duration}'")
            })?;
        }

        let contracts = contracts.unwrap_or_default();
        let instrument_ids = instrument_ids.unwrap_or_default();

        if contracts.is_empty() && instrument_ids.is_empty() {
            anyhow::bail!("Either contracts or instrument_ids must be provided");
        }

        // Convert instrument IDs to contracts using instrument provider
        let mut all_contracts = contracts;

        for instrument_id in instrument_ids {
            // Try to find instrument in provider first
            if self.instrument_provider.find(&instrument_id).is_none() {
                // Auto-fetch if not cached
                if let Err(e) = self
                    .instrument_provider
                    .fetch_contract_details(&self.ib_client, instrument_id, false, None)
                    .await
                {
                    tracing::warn!(
                        "Failed to auto-fetch contract details for {}: {}",
                        instrument_id,
                        e

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass at least one InstrumentId in instrument_ids (e.g. "EUR/USD.IDEALPRO").
  2. Pass a non-empty Vec<Contract> if you already hold IB contracts.
  3. Check the upstream filter/config that produced the empty list and populate it.

Example fix

// before
let ids: Vec<InstrumentId> = Vec::new();
client.request_bars(&["1-HOUR-LAST"], end, None, Some("5 D"), None, Some(ids), true, 60).await?;
// after
let ids = vec![InstrumentId::from("EUR/USD.IDEALPRO")];
client.request_bars(&["1-HOUR-LAST"], end, None, Some("5 D"), None, Some(ids), true, 60).await?;
Defensive patterns

Strategy: validation

Validate before calling

if contracts.as_ref().map_or(true, |c| c.is_empty())
    && instrument_ids.as_ref().map_or(true, |i| i.is_empty()) {
    return Err("no instruments selected for bar request");
}

Prevention

When it happens

Trigger: Calling request_bars with contracts=None and instrument_ids=None, or with empty vectors for both (they are unwrap_or_default-ed).

Common situations: An upstream filter produced zero instruments; a config list left empty; a wrapper that passes its own (possibly empty) Option straight through after having consumed the ids elsewhere.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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