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
- Read the comma-separated list in the message and fix each listed instrument ID in your configuration (symbol, venue, security type).
- Validate each instrument exists on IB by searching it in TWS before adding it to config.
- Remove or replace expired/delisted instruments from the configured set.
- 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
- Keep instrument config lists fully qualified (SYMBOL.VENUE)
- Periodically audit config for expired/delisted contracts
- Test each new instrument in TWS before adding it to the adapter config
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
- Failed to resolve instrument ID for contract {}:{}:{}
- Cannot resolve BAG contract without combo legs or cached con
- Interactive Brokers execution client_id must not be a multip
- Unrecognized execution timezone '{tz_str}' in '{time_str}'.
- Chain ID mismatch at connect: expected {expected_chain_id},
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9066393b8938fecf.
Report an issue: GitHub.