nautechsystems/nautilus_trader · error · anyhow::Error
Cannot resolve BAG contract without combo legs or cached con
Error message
Cannot resolve BAG contract without combo legs or cached contract ID
What it means
BAG (spread/combo) contracts in IB carry their definition in combo_legs. This error fires when the adapter is asked to resolve a BAG contract's instrument ID but the contract has no combo legs and no cached contract ID, so there is no leg data from which to derive the spread instrument ID.
Source
Thrown at crates/adapters/interactive_brokers/src/providers/instruments.rs:515
return self.resolve_spread_instrument_id_for_contract(contract);
}
let venue = self.determine_venue(contract, None);
match self.config.symbology_method {
SymbologyMethod::Simplified => {
ib_contract_to_instrument_id_simplified(contract, Some(venue))
}
SymbologyMethod::Raw => ib_contract_to_instrument_id_raw(contract, Some(venue)),
}
}
fn resolve_spread_instrument_id_for_contract(
&self,
contract: &Contract,
) -> anyhow::Result<InstrumentId> {
if contract.combo_legs.is_empty() {
anyhow::bail!("Cannot resolve BAG contract without combo legs or cached contract ID");
}
let mut leg_tuples = Vec::with_capacity(contract.combo_legs.len());
for combo_leg in &contract.combo_legs {
let leg_instrument_id = self
.get_instrument_id_by_contract_id(combo_leg.contract_id)
.with_context(|| {
format!(
"Cannot resolve BAG leg con_id {} to cached instrument ID",
combo_leg.contract_id
)
})?;
let ratio = IbAction::from_str(combo_leg.action.as_str())
.context("Invalid BAG combo leg action")?
.signed_multiplier()
* combo_leg.ratio;
View on GitHub (pinned to 18893faf8b)
Solutions
- Populate contract.combo_legs with the spread's legs (each with con_id, ratio, and action) before resolution.
- Fetch full contract details for the BAG con_id first so the cached ID/legs are available.
- For non-BAG contracts, don't route through the spread-resolution path.
- Verify the security type is actually BAG; a mislabeled contract may bypass leg construction.
Example fix
// before: empty BAG contract
let contract = Contract { security_type: SecurityType::Bag, ..Default::default() };
// after: BAG contract with legs
let contract = Contract {
security_type: SecurityType::Bag,
combo_legs: vec![
ComboLeg { con_id: 552824014, ratio: 1, action: "BUY".into(), ..Default::default() },
ComboLeg { con_id: 552824046, ratio: 1, action: "SELL".into(), ..Default::default() },
],
..Default::default()
}; Defensive patterns
Strategy: validation
Validate before calling
fn can_resolve_bag(contract: &Contract) -> bool {
contract.security_type != SecurityType::Bag
|| !contract.combo_legs.is_empty()
|| contract.con_id != 0 // cached contract ID available
} Prevention
- Never construct BAG contracts without combo_legs
- Fetch full contract details before spread resolution
- Route single-instrument contracts to the non-spread path
When it happens
Trigger: resolve_spread_instrument_id_for_contract receives a Contract with security_type BAG whose combo_legs list is empty and for which no prior contract-details response cached an identifier.
Common situations: Constructing a BAG contract by hand and forgetting to populate combo_legs, or receiving a bare BAG contract from a subscription callback before full contract details arrived.
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
- Resolved BAG spread {spread_instrument_id} is not cached
- Invalid BAG contract: must have security_type=Spread and non
- No valid legs loaded for BAG contract
- Failed to resolve instrument ID for contract {}:{}:{}
- Unable to resolve configured Interactive Brokers instruments
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7a2bb120b7a2fdc0.
Report an issue: GitHub.