{"record":{"id":"966c49a54df2c7ac","repo":"QuantConnect/Lean","slug":"expected-expected-chain-count-futures-in-chain-o","errorCode":null,"errorMessage":"Expected {expected_chain_count} futures in chain on {date}, but got {actual_chain_count}","messagePattern":"Expected (.+?) futures in chain on (.+?), but got (.+?)","errorType":"exception","errorClass":"RegressionTestException","httpStatus":null,"severity":"error","filePath":"Algorithm.Python/FutureUniverseHistoryRegressionAlgorithm.py","lineNumber":43,"sourceCode":"\n        future = self.add_future(Futures.Indices.SP_500_E_MINI).symbol\n\n        historical_futures_data_df = self.history(FutureUniverse, future, 3, flatten=True)\n\n        # Level 0 of the multi-index is the date, we expect 3 dates, 3 future chains\n        if historical_futures_data_df.index.levshape[0] != 3:\n            raise RegressionTestException(f\"Expected 3 futures chains from history request, \"\n                                          f\"but got {historical_futures_data_df.index.levshape[1]}\")\n\n        for date in historical_futures_data_df.index.levels[0]:\n            expected_chain = list(self.future_chain_provider.get_future_contract_list(future, date))\n            expected_chain_count = len(expected_chain)\n\n            actual_chain = historical_futures_data_df.loc[date]\n            actual_chain_count = len(actual_chain)\n\n            if expected_chain_count != actual_chain_count:\n                raise RegressionTestException(f\"Expected {expected_chain_count} futures in chain on {date}, \"\n                                              f\"but got {actual_chain_count}\")\n\n            for i, symbol in enumerate(actual_chain.index):\n                expected_symbol = expected_chain[i]\n                if symbol != expected_symbol:\n                    raise RegressionTestException(f\"Expected symbol {expected_symbol} at index \"\n                                                  f\" {i} on {date}, but got {symbol}\")\n","sourceCodeStart":25,"sourceCodeEnd":51,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Python/FutureUniverseHistoryRegressionAlgorithm.py#L25-L51","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Pre-compare counts per date\nfor date in df.index.levels[0]:\n    expected = len(list(self.future_chain_provider.get_future_contract_list(future, date)))\n    actual = len(df.loc[date])\n    if expected != actual:\n        self.debug(f\"Chain mismatch on {date}: expected={expected} actual={actual}\")","typeGuard":"def chain_counts_match(provider, future, df) -> bool:\n    return all(\n        len(list(provider.get_future_contract_list(future, d))) == len(df.loc[d])\n        for d in df.index.levels[0]\n    )","tryCatchPattern":null,"preventionTips":["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."],"tags":["quantconnect","futures","future-universe","future-chain-provider","history-request","regression-test"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}