QuantConnect/Lean · error · RegressionTestException

Unexpected delisting events

Error message

Unexpected delisting events

What it means

This assertion sits in OnDelistings of a regression algorithm that sells an option, expects it to be assigned (stock delivered), then expects the option to delist. It enforces that every Delistings collection delivered to the algorithm contains the specific option symbol (_option) the test holds. QuantConnect Lean dispatches a Delistings collection per time step; if delistings.TryGetValue(_option, ...) returns false, the engine sent a delisting for a symbol other than the one the test tracks, which means the delisting pipeline produced an off-target or spurious event.

Source

Thrown at Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs:130

                }
            }
            else if (orderEvent.Status == OrderStatus.Canceled)
            {
                // The delisted event is received before the order is canceled
                if (!_optionSold || !_optionAssigned || !_stockAssigned || !_optionDelistedWarningReceived || !_optionDelisted)
                {
                    throw new RegressionTestException($"Unexpected cancel event: {orderEvent}");
                }

                _orderCanceled = true;
            }
        }

        public override void OnDelistings(Delistings delistings)
        {
            if (!delistings.TryGetValue(_option, out var delisting))
            {
                throw new RegressionTestException($"Unexpected delisting events");
            }

            if (delisting.Type == DelistingType.Warning)
            {
                if (!_optionSold || !_optionAssigned || !_stockAssigned || _optionDelistedWarningReceived)
                {
                    throw new RegressionTestException($"Unexpected delisting warning event: {delisting}");
                }

                _optionDelistedWarningReceived = true;
            }
            else
            {
                if (!_optionSold || !_optionAssigned || !_stockAssigned || !_optionDelistedWarningReceived || _optionDelisted)
                {
                    throw new RegressionTestException($"Unexpected delisting event: {delisting}");
                }

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Log every entry in the Delistings collection at the throw site to see which Symbol/Type arrived unexpectedly.
  2. Trace delisting event generation in Lean (Delisting provider / SecurityManager) for the unexpected symbol and find who created that security.
  3. If the extra event is expected after your engine change, widen the assertion to allow it; otherwise fix the engine to stop emitting the spurious delisting.

Example fix

// before
if (!delistings.TryGetValue(_option, out var delisting))
{
    throw new RegressionTestException($"Unexpected delisting events");
}

// after (diagnostic + tolerant of known extra symbol)
if (!delistings.TryGetValue(_option, out var delisting))
{
    throw new RegressionTestException(
        $"Unexpected delisting events. Got: {string.Join(", ", delistings.Select(d => $"{d.Symbol}:{d.Type}"))}");
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the delistings collection before asserting on a single symbol
if (delistings == null || !delistings.Any())
{
    // no delistings this step; nothing to assert
    return;
}
var unexpected = delistings.Where(d => d.Symbol != _option).ToList();
if (unexpected.Count > 0)
{
    throw new RegressionTestException(
        $"Off-target delisting(s): {string.Join(", ", unexpected.Select(d => $"{d.Symbol}:{d.Type}"))}");
}

Try / catch

try { var delisting = delistings[_option]; /* use */ }
catch (KeyNotFoundException) { /* log full collection, then rethrow with context */ }

Prevention

When it happens

Trigger: A delisting event arrives whose Symbol != _option (e.g. the underlying stock delists, a second option contract is delisted, or the collection is empty). Triggered by changes to the delisting dispatcher in AlgorithmManager or the delisting event provider emitting for an unexpected canonical/security.

Common situations: Refactoring SecurityService/SubscriptionManager so a duplicate security lingers and delists; introducing a new auxiliary symbol in the test that carries delisting metadata; data-file changes adding delisting info for an extra symbol; an option canonical symbol resolution change.

Related errors


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