{"record":{"id":"c6013bb6954d35a5","repo":"QuantConnect/Lean","slug":"expected-expectedsymbols-count-stocks-to-be-adde","errorCode":null,"errorMessage":"Expected {ExpectedSymbols.Count} stocks to be added to the algorithm, but found {changes.AddedSecurities.Count}","messagePattern":"Expected (.+?) stocks to be added to the algorithm, but found (.+?)","errorType":"exception","errorClass":"RegressionTestException","httpStatus":null,"severity":"error","filePath":"Algorithm.CSharp/CustomUniverseImmediateSelectionRegressionAlgorithm.cs","lineNumber":92,"sourceCode":"\n        public override void OnSecuritiesChanged(SecurityChanges changes)\n        {\n            if (!_selected)\n            {\n                throw new RegressionTestException(\"Universe selection should have been triggered right away\");\n            }\n\n            if (!_securitiesChanged)\n            {\n                // Selection should be happening right on algorithm start\n                if (Time != StartDate)\n                {\n                    throw new RegressionTestException(\"Universe selection should have been triggered right away\");\n                }\n\n                if (changes.AddedSecurities.Count != ExpectedSymbols.Count)\n                {\n                    throw new RegressionTestException($\"Expected {ExpectedSymbols.Count} stocks to be added to the algorithm, \" +\n                        $\"but found {changes.AddedSecurities.Count}\");\n                }\n\n                if (!ExpectedSymbols.All(x => changes.AddedSecurities.Any(security => security.Symbol == x)))\n                {\n                    throw new RegressionTestException(\"Expected symbols were not added to the algorithm\");\n                }\n\n                _securitiesChanged = true;\n            }\n        }\n\n        public override void OnEndOfAlgorithm()\n        {\n            if (_firstOnData || !_selected || !_securitiesChanged)\n            {\n                throw new RegressionTestException(\"Expected events didn't happen\");\n            }","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.CSharp/CustomUniverseImmediateSelectionRegressionAlgorithm.cs#L74-L110","documentation":"This RegressionTestException is thrown inside OnSecuritiesChanged of a universe-selection regression algorithm. It asserts that the number of securities the LEAN engine added via the custom universe selector exactly matches the count of symbols the selector function returned (ExpectedSymbols.Count). LEAN throws it because the universe-selection pipeline must faithfully materialize every symbol the selector function yields into SecurityChanges.AddedSecurities on the very first algorithm time-step.","triggerScenarios":"The custom AddUniverse selector returns an array of tickers (e.g. new[] { \"SPY\", \"GOOG\", \"APPL\" }) but changes.AddedSecurities.Count differs from the returned array length. This happens when the engine filters out symbols (unknown market data, delisted, duplicate), when the selector returns a different count than ExpectedSymbols, or when universe-selection timing changed so securities are batched differently.","commonSituations":"Modifying the LEAN universe-selection pipeline (e.g. filtering, deduplication, or batching logic), changing the selector function's return value, upgrading to a LEAN version that altered how AddedSecurities is populated, or running with a data provider that lacks some requested symbols.","solutions":["Inspect changes.AddedSecurities at the throw point to see which symbols were actually added versus ExpectedSymbols.","Verify the AddUniverse selector function returns exactly the symbols in ExpectedSymbols (no typos like \"APPL\" vs \"AAPL\").","Check that the data provider has factor files and price data for every requested symbol so the engine does not silently drop any.","If you changed the engine's universe-selection code, trace SecurityChanges construction to ensure all selected symbols appear in AddedSecurities."],"exampleFix":"// before\nAddUniverse(SecurityType.Equity, \"my-universe\", Resolution.Daily, Market.USA, UniverseSettings,\n    time => new[] { \"SPY\", \"GOOG\", \"APPL\" }); // typo: APPL not AAPL\n\n// after\nAddUniverse(SecurityType.Equity, \"my-universe\", Resolution.Daily, Market.USA, UniverseSettings,\n    time => new[] { \"SPY\", \"GOOG\", \"AAPL\" }); // corrected ticker","handlingStrategy":"validation","validationCode":"// Before relying on AddedSecurities, validate the selector output and engine result match\npublic override void OnSecuritiesChanged(SecurityChanges changes)\n{\n    var expected = new[] { \"SPY\", \"GOOG\", \"AAPL\" };\n    var actual = changes.AddedSecurities.Select(s => s.Symbol.Value).ToHashSet();\n    var missing = expected.Where(t => !actual.Contains(t)).ToList();\n    if (missing.Any())\n        Log($\"Warning: missing securities: {string.Join(\", \", missing)}\");\n    // proceed only if all expected are present\n}","typeGuard":"// Type guard for SecurityChanges shape\nif (changes?.AddedSecurities == null || changes.AddedSecurities.Count == 0) return;\nif (changes.AddedSecurities.Any(s => s?.Symbol == null)) return;","tryCatchPattern":null,"preventionTips":["Keep the ExpectedSymbols list and the AddUniverse selector return value in sync — derive one from the other.","Validate all tickers in the selector exist in the data provider before returning them.","Log changes.AddedSecurities on first invocation to catch mismatches early."],"tags":["quantconnect","lean","universe-selection","regression-test","securities"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}