nautechsystems/nautilus_trader · error · anyhow::Error

Unable to resolve configured Interactive Brokers instruments

Error message

Unable to resolve configured Interactive Brokers instruments: {}

What it means

Raised when one or more instruments configured for the Interactive Brokers adapter could not be resolved to IB contracts during initialization. load_configured_instruments aggregates all unresolved instrument IDs and fails fast, listing them, so the adapter never starts with a partially loaded instrument cache.

Source

Thrown at crates/adapters/interactive_brokers/src/providers/instruments.rs:293

        }

        for (index, contract_spec) in self.config.load_contracts.iter().enumerate() {
            let mut contract_ids =
                loader.load_contract(contract_spec).await.with_context(|| {
                    format!(
                        "Failed to load configured IB contract at index {index}: {contract_spec}"
                    )
                })?;

            if contract_ids.is_empty() {
                unresolved.push(format!("contract at index {index}: {contract_spec}"));
            } else {
                loaded_ids.append(&mut contract_ids);
            }
        }

        if !unresolved.is_empty() {
            anyhow::bail!(
                "Unable to resolve configured Interactive Brokers instruments: {}",
                unresolved.join(", ")
            );
        }

        loaded_ids.sort_unstable();
        loaded_ids.dedup();
        Ok(loaded_ids)
    }

    /// Adds instruments already held by the Nautilus cache into the provider cache.
    ///
    /// This mirrors the Python provider's use of `client._cache` for venue resolution and for
    /// recovering stored IB contract metadata from `instrument.info["contract"]`.
    pub fn add_cached_instruments<I>(&self, instruments: I) -> usize
    where
        I: IntoIterator<Item = InstrumentAny>,
    {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the comma-separated list in the message and fix each listed instrument ID in your configuration (symbol, venue, security type).
  2. Validate each instrument exists on IB by searching it in TWS before adding it to config.
  3. Remove or replace expired/delisted instruments from the configured set.
  4. Ensure the instrument loader's venue config matches IB expectations (e.g. use venue codes IB recognizes like CME, SMART).

Example fix

// before: config with unresolvable instrument
instruments = ["EQ.NOSUCHTICKER"]
// after: corrected, fully qualified instrument
instruments = ["EQ.AAPL"]  // symbol exists at IB under SMART/NASDAQ
Defensive patterns

Strategy: validation

Validate before calling

fn validate_configured_instruments(ids: &[String]) -> Result<(), String> {
    let bad: Vec<_> = ids.iter().filter(|id| !id.contains('.')).collect();
    if bad.is_empty() { Ok(()) } else { Err(format!("not fully qualified: {:?}", bad)) }
}

Prevention

When it happens

Trigger: initialize_with_loader is called with configured instrument IDs that the contract-resolution path cannot map to IB contracts (unknown symbols, wrong security type, expired contracts, or contracts IB returns no details for).

Common situations: Typos in instrument config, symbols missing an exchange suffix, requesting instruments from exchanges without IB coverage, or running with stale configs referencing delisted/expired contracts.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/9066393b8938fecf. Report an issue: GitHub.