QuantConnect/Lean · error · RegressionTestException
Expected symbols were not added to the algorithm
Error message
Expected symbols were not added to the algorithm
What it means
This RegressionTestException is thrown in OnSecuritiesChanged after the AddedSecurities count check passes. It asserts that every symbol in ExpectedSymbols is present in changes.AddedSecurities by value equality. LEAN uses it to verify the universe selector produced not just the right *count* of securities but the correct *identities* — symbol, security type, and market must all match.
Source
Thrown at Algorithm.CSharp/CustomUniverseImmediateSelectionRegressionAlgorithm.cs:98
}
if (!_securitiesChanged)
{
// Selection should be happening right on algorithm start
if (Time != StartDate)
{
throw new RegressionTestException("Universe selection should have been triggered right away");
}
if (changes.AddedSecurities.Count != ExpectedSymbols.Count)
{
throw new RegressionTestException($"Expected {ExpectedSymbols.Count} stocks to be added to the algorithm, " +
$"but found {changes.AddedSecurities.Count}");
}
if (!ExpectedSymbols.All(x => changes.AddedSecurities.Any(security => security.Symbol == x)))
{
throw new RegressionTestException("Expected symbols were not added to the algorithm");
}
_securitiesChanged = true;
}
}
public override void OnEndOfAlgorithm()
{
if (_firstOnData || !_selected || !_securitiesChanged)
{
throw new RegressionTestException("Expected events didn't happen");
}
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public bool CanRunLocally { get; } = true;View on GitHub (pinned to d2c3659f87)
Solutions
- Log both ExpectedSymbols and changes.AddedSecurities to identify which symbol is missing or mismatched.
- Confirm the selector function returns the exact same tickers every call (no conditional logic altering the set).
- Verify that Symbol.Create in ExpectedSymbols uses the same SecurityType and Market as the AddUniverse call.
- If testing engine changes, check that universe-selection output is not reordered or remapped before reaching OnSecuritiesChanged.
Example fix
// before
private static readonly List<Symbol> ExpectedSymbols = new List<Symbol>()
{
Symbol.Create("SPY", SecurityType.Equity, Market.USA),
Symbol.Create("GOOG", SecurityType.Equity, Market.USA),
Symbol.Create("APPL", SecurityType.Equity, Market.USA) // wrong
};
// selector returns: new[] { "SPY", "GOOG", "AAPL" }
// after — keep ExpectedSymbols in sync with the selector output
private static readonly List<Symbol> ExpectedSymbols = new List<Symbol>()
{
Symbol.Create("SPY", SecurityType.Equity, Market.USA),
Symbol.Create("GOOG", SecurityType.Equity, Market.USA),
Symbol.Create("AAPL", SecurityType.Equity, Market.USA)
}; Defensive patterns
Strategy: validation
Validate before calling
// Validate symbol identity before the assertion
var actualSet = changes.AddedSecurities.Select(s => s.Symbol).ToHashSet();
var missingSymbols = ExpectedSymbols.Where(s => !actualSet.Contains(s)).ToList();
if (missingSymbols.Any())
Debug($"Missing symbols: {string.Join(", ", missingSymbols.Select(s => s.Value))}"); Type guard
bool SymbolsMatch(List<Symbol> expected, IEnumerable<Symbol> actual)
{
var actualSet = actual.ToHashSet();
return expected.All(s => actualSet.Contains(s));
} Prevention
- Use Symbol.Create with consistent SecurityType and Market in both ExpectedSymbols and the selector.
- Avoid conditional logic in the selector that could return different tickers on different calls.
- Unit-test the selector function independently before wiring it to AddUniverse.
When it happens
Trigger: The AddedSecurities count equals ExpectedSymbols.Count (3) but the actual symbols differ — e.g. the selector returned different tickers than expected, or the engine resolved tickers to symbols with a different SecurityType or Market than ExpectedSymbols specifies. Also fires if Symbol equality semantics changed (SID vs ticker-based).
Common situations: Selector function logic changed to return different tickers under some conditions, symbol resolution maps a ticker to a different market (e.g. Market.USA vs Market.OANDA), or a LEAN upgrade changed Symbol equality or SymbolCache behavior.
Related errors
- Expected {ExpectedSymbols.Count} stocks to be added to the a
- Expected events didn't happen
- Unexpected Bar error
- Unexpected data count: {slice.Count}
- Unexpected ActiveSecurities count: {ActiveSecurities.Count}
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/f4ead13739c5b565.
Report an issue: GitHub.