QuantConnect/Lean · error · RegressionTestException
Expected {expected_chain_count} futures in chain on {date},
Error message
Expected {expected_chain_count} futures in chain on {date}, but got {actual_chain_count} What it means
Per-date chain-count comparison. For each date in the history result, the test contrasts len(future_chain_provider.get_future_contract_list(future, date)) against the row count in the historical DataFrame for that date. A mismatch aborts, proving the history result and the live chain provider agree.
Source
Thrown at Algorithm.Python/FutureUniverseHistoryRegressionAlgorithm.py:43
future = self.add_future(Futures.Indices.SP_500_E_MINI).symbol
historical_futures_data_df = self.history(FutureUniverse, future, 3, flatten=True)
# Level 0 of the multi-index is the date, we expect 3 dates, 3 future chains
if historical_futures_data_df.index.levshape[0] != 3:
raise RegressionTestException(f"Expected 3 futures chains from history request, "
f"but got {historical_futures_data_df.index.levshape[1]}")
for date in historical_futures_data_df.index.levels[0]:
expected_chain = list(self.future_chain_provider.get_future_contract_list(future, date))
expected_chain_count = len(expected_chain)
actual_chain = historical_futures_data_df.loc[date]
actual_chain_count = len(actual_chain)
if expected_chain_count != actual_chain_count:
raise RegressionTestException(f"Expected {expected_chain_count} futures in chain on {date}, "
f"but got {actual_chain_count}")
for i, symbol in enumerate(actual_chain.index):
expected_symbol = expected_chain[i]
if symbol != expected_symbol:
raise RegressionTestException(f"Expected symbol {expected_symbol} at index "
f" {i} on {date}, but got {symbol}")
View on GitHub (pinned to d2c3659f87)
Solutions
- Compare expected_chain and actual_chain contents for the failing date to identify added/missing contracts.
- Confirm both calls use the same date resolution (UTC vs exchange tz).
- Re-pull or re-run the data generator for the affected date.
- If the chain provider is now intentionally richer, update the regression expectations.
Defensive patterns
Strategy: validation
Validate before calling
# Pre-compare counts per date
for date in df.index.levels[0]:
expected = len(list(self.future_chain_provider.get_future_contract_list(future, date)))
actual = len(df.loc[date])
if expected != actual:
self.debug(f"Chain mismatch on {date}: expected={expected} actual={actual}") Type guard
def chain_counts_match(provider, future, df) -> bool:
return all(
len(list(provider.get_future_contract_list(future, d))) == len(df.loc[d])
for d in df.index.levels[0]
) Prevention
- Resolve dates in the same timezone for both history and chain provider calls.
- Refresh data if the chain provider and history endpoints disagree.
- Log expected vs actual chain contents per date when debugging.
- Confirm provider behaviour after engine upgrades.
When it happens
Trigger: FutureUniverse history snapshot taken at a different time-of-day than the chain provider query; the chain provider returning a different contract set after a data refresh; stale or partial chain files for the queried date.
Common situations: Data provider inconsistency between history and chain endpoints; timezone differences making 'date' resolve to adjacent days; data refreshes that add/remove contracts; engine changes to FutureUniverse filtering.
Related errors
- Expected 3 futures chains from history request, but got {his
- Expected symbol {expected_symbol} at index {i} on {date}, b
- [{UtcTime}] We hold a delisted securities: {string.Join(",",
- Expected at least two future contracts with option chains, b
- The Exchange hours was closed, verify 'extended_market_hours
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/966c49a54df2c7ac.
Report an issue: GitHub.