{"record":{"id":"f0ccbe270254c6e6","repo":"QuantConnect/Lean","slug":"unexpected-delisting-warning-event-delisting","errorCode":null,"errorMessage":"Unexpected delisting warning event: {delisting}","messagePattern":"Unexpected delisting warning event: (.+?)","errorType":"exception","errorClass":"RegressionTestException","httpStatus":null,"severity":"error","filePath":"Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs","lineNumber":137,"sourceCode":"                    throw new RegressionTestException($\"Unexpected cancel event: {orderEvent}\");\n                }\n\n                _orderCanceled = true;\n            }\n        }\n\n        public override void OnDelistings(Delistings delistings)\n        {\n            if (!delistings.TryGetValue(_option, out var delisting))\n            {\n                throw new RegressionTestException($\"Unexpected delisting events\");\n            }\n\n            if (delisting.Type == DelistingType.Warning)\n            {\n                if (!_optionSold || !_optionAssigned || !_stockAssigned || _optionDelistedWarningReceived)\n                {\n                    throw new RegressionTestException($\"Unexpected delisting warning event: {delisting}\");\n                }\n\n                _optionDelistedWarningReceived = true;\n            }\n            else\n            {\n                if (!_optionSold || !_optionAssigned || !_stockAssigned || !_optionDelistedWarningReceived || _optionDelisted)\n                {\n                    throw new RegressionTestException($\"Unexpected delisting event: {delisting}\");\n                }\n\n                _optionDelisted = true;\n            }\n        }\n\n        public override void OnEndOfAlgorithm()\n        {\n            if (!_optionSold)","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs#L119-L155","documentation":"Once a delisting for _option is confirmed, this check applies to the DelistingType.Warning phase. It requires a strict ordering: the option must already have been sold (_optionSold), assigned (_optionAssigned), the underlying stock assigned (_stockAssigned), and no warning received yet (!_optionDelistedWarningReceived). If the warning arrives before all those preconditions hold, the engine delivered the delisting warning out of expected sequence.","triggerScenarios":"DelistingType.Warning arrives before the assignment events fired, or a warning fires twice (second one trips _optionDelistedWarningReceived). Caused by reordering of the assignment/delisting pipeline or by option assignment being skipped.","commonSituations":"Changing exercise/assignment processing order versus delisting detection; data where the option's last trading date moves earlier than the assignment date; a regression in the OptionAssignment service.","solutions":["Capture the values of _optionSold/_optionAssigned/_stockAssigned/_optionDelistedWarningReceived at throw time to see which precondition is unmet.","Inspect the OptionAssignment/Exercise pipeline logs to confirm the assignment event actually fired before the delisting warning.","Correct the engine ordering so assignment precedes the delisting warning, or adjust the expected sequence if the new order is intentional."],"exampleFix":"// before\nif (!_optionSold || !_optionAssigned || !_stockAssigned || _optionDelistedWarningReceived)\n{\n    throw new RegressionTestException($\"Unexpected delisting warning event: {delisting}\");\n}\n\n// after (include which flag is wrong)\nvar unmet = new[] { (\"optionSold\", _optionSold), (\"optionAssigned\", _optionAssigned), (\"stockAssigned\", _stockAssigned), (\"warningAlready\", _optionDelistedWarningReceived) }\n    .Where(x => !x.Item2).Select(x => x.Item1);\nthrow new RegressionTestException($\"Unexpected delisting warning event: {delisting}. Unmet: {string.Join(\", \", unmet)}\");","handlingStrategy":"validation","validationCode":"static bool PreconditionsMet(params (string name, bool ok)[] checks)\n    => checks.All(c => c.ok);\n\nvar ok = PreconditionsMet(\n    (\"optionSold\", _optionSold),\n    (\"optionAssigned\", _optionAssigned),\n    (\"stockAssigned\", _stockAssigned),\n    (\"warningNotReceived\", !_optionDelistedWarningReceived));\nif (!ok) throw new RegressionTestException(\"Delisting warning received before preconditions met\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Track lifecycle state with an explicit state machine enum rather than independent booleans to make ordering impossible to violate silently.","Add the flag values to every lifecycle assertion message for fast triage.","Unit-test the assignment/delisting ordering in Lean core, not only via this regression algorithm."],"tags":["quantconnect","lean","regression-test","options","delisting","state-machine","ordering"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}