QuantConnect/Lean · error · RegressionTestException

{Time} unexpected symbol changed event {changedEvent}!

Error message

{Time} unexpected symbol changed event {changedEvent}!

What it means

This futures regression algorithm asserts that continuous-contract SymbolChangedEvents (rollovers) only occur at midnight (Time.TimeOfDay == TimeSpan.Zero), i.e. at the daily session boundary. A symbol-change event at any other intraday time is unexpected and indicates mapping fired at the wrong point in the trading day.

Source

Thrown at Algorithm.CSharp/BasicTemplateFuturesAlgorithm.cs:82

            var benchmark = AddEquity("SPY");
            SetBenchmark(benchmark.Symbol);

            var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
            SetSecurityInitializer(security => seeder.SeedSecurity(security));
        }

        /// <summary>
        /// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event
        /// </summary>
        /// <param name="slice">The current slice of data keyed by symbol string</param>
        public override void OnData(Slice slice)
        {
            foreach (var changedEvent in slice.SymbolChangedEvents.Values)
            {
                Debug($"{Time} - SymbolChanged event: {changedEvent}");
                if (Time.TimeOfDay != TimeSpan.Zero)
                {
                    throw new RegressionTestException($"{Time} unexpected symbol changed event {changedEvent}!");
                }
            }

            if (!Portfolio.Invested)
            {
                foreach(var chain in slice.FutureChains)
                {
                    // find the front contract expiring no earlier than in 90 days
                    var contract = (
                        from futuresContract in chain.Value.OrderBy(x => x.Expiry)
                        where futuresContract.Expiry > Time.Date.AddDays(90)
                        select futuresContract
                    ).FirstOrDefault();

                    // if found, trade it
                    if (contract != null)
                    {
                        _contractSymbol = contract.Symbol;

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Confirm the continuous contract's DataMappingMode maps at the daily boundary consistent with the data set.
  2. Verify the backtest resolution and session-clock alignment so Time reflects the correct boundary.
  3. If your data legitimately rolls intraday (e.g. a custom feed), relax the midnight assertion to your expected rollover time.
  4. Ensure the futures chain data is complete so Lean does not fall back to an alternate rollover instant.

Example fix

// before
if (Time.TimeOfDay != TimeSpan.Zero) { throw ...; }

// after: assert rollover only at the configured mapping time
if (Time.TimeOfDay != ExpectedRolloverTime) { throw ...; }
Defensive patterns

Strategy: validation

Validate before calling

foreach (var changedEvent in slice.SymbolChangedEvents.Values)
{
    if (Time.TimeOfDay != TimeSpan.Zero)
    {
        Log($"{Time} - Off-boundary rollover: {changedEvent}. Verify mapping mode/feed.");
    }
}

Prevention

When it happens

Trigger: A SymbolChangedEvent arrives in OnData while Time.TimeOfDay != TimeSpan.Zero — Lean remapped the continuous contract mid-session instead of at the midnight/day boundary.

Common situations: DataMappingMode or contract rollover timing changed in the engine; intraday data triggered an early remap; the data feed's contract chain shifted mid-day; a version change altered when mapping events are emitted relative to the session clock.

Related errors


AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13). Data as JSON: /api/errors/f9ad97cbd199e41a. Report an issue: GitHub.