{"record":{"id":"df2e23c5446ae87e","repo":"QuantConnect/Lean","slug":"field-self-ticket-not-expected-no-be-assigned-on-t","errorCode":null,"errorMessage":"Field self.ticket not expected no be assigned on the first order event","messagePattern":"Field self\\.ticket not expected no be assigned on the first order event","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"Algorithm.Python/OrderTicketAssignmentDemoAlgorithm.py","lineNumber":46,"sourceCode":"\n        self.trade_count = 0\n        self.consolidate(self._symbol, timedelta(hours=1), self.hour_consolidator)\n\n    def hour_consolidator(self, bar: TradeBar):\n        # Reset self.ticket to None on each new bar\n        self.ticket = None\n        self.ticket = self.market_order(self._symbol, 1, asynchronous=True)\n        self.debug(f\"{self.time}: Buy: Price {bar.price}, order_id: {self.ticket.order_id}\")\n        self.trade_count += 1\n\n    def on_order_event(self, order_event: OrderEvent):\n        # We cannot access self.ticket directly because it is assigned asynchronously:\n        # this order event could be triggered before self.ticket is assigned.\n        ticket = order_event.ticket\n        if ticket is None:\n            raise AssertionError(\"Expected order ticket in order event to not be null\")\n        if order_event.status == OrderStatus.SUBMITTED and self.ticket is not None:\n            raise AssertionError(\"Field self.ticket not expected no be assigned on the first order event\")\n\n        self.debug(ticket.to_string())\n\n    def on_end_of_algorithm(self):\n        # Just checking that orders were placed\n        if not self.portfolio.invested or self.trade_count != self.transactions.orders_count:\n            raise AssertionError(f\"Expected the portfolio to have holdings and to have {self.trade_count} trades, but had {self.transactions.orders_count}\")\n","sourceCodeStart":28,"sourceCodeEnd":54,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Python/OrderTicketAssignmentDemoAlgorithm.py#L28-L54","documentation":"This assertion encodes the async-ordering invariant the demo teaches: the first OrderEvent (status SUBMITTED) for an asynchronous market order can fire before the self.ticket = self.market_order(...) assignment completes in the consolidator thread. Therefore, at the moment a SUBMITTED event is processed, self.ticket should still be None. If self.ticket is already assigned when the SUBMITTED event arrives, the async ordering the demo relies on has changed (e.g. the assignment now completes synchronously before the event is dispatched).","triggerScenarios":"on_order_event receives an event with order_event.status == OrderStatus.SUBMITTED while self.ticket is not None. Triggered when the market_order(...) return assignment completes before the SUBMITTED event is delivered, breaking the demo's assumed race window.","commonSituations":"A Lean change making asynchronous order submission/ticket assignment synchronous; threading/event-dispatch changes so the consolidator thread finishes assigning self.ticket before the event handler runs; running in a single-threaded scheduler where the race never occurs.","solutions":["If the engine legitimately now assigns the ticket before the SUBMITTED event, update the demo's invariant (this assertion may be obsolete).","Keep relying on order_event.ticket (not self.ticket) inside on_order_event to avoid the race entirely.","Confirm asynchronous=True still defers ticket assignment; if behavior changed, document the new contract.","Move the self.ticket assignment off the hot path or use a queue so the ordering remains as the demo intends."],"exampleFix":"# before: assumes self.ticket is None during the SUBMITTED event\nif order_event.status == OrderStatus.SUBMITTED and self.ticket is not None:\n    raise AssertionError(...)\n# after: rely on the event's own ticket, not the race-dependent self.ticket\nticket = order_event.ticket\nif ticket is None:\n    raise AssertionError('event ticket should be populated')","handlingStrategy":"validation","validationCode":"# Do not depend on the race; use the event's own ticket\nif order_event.status == OrderStatus.SUBMITTED:\n    # self.ticket may or may not be assigned yet; that is fine\nticket = order_event.ticket\nif ticket is None:\n    raise AssertionError('event ticket should be populated')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never read a shared self.ticket inside on_order_event for async orders; use order_event.ticket.","If the engine's async semantics change, update the demo invariant rather than relying on a race.","Document whether SUBMITTED events precede or follow ticket assignment."],"tags":["orders","order-ticket","asynchronous","race-condition","order-event","quantconnect","demo"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}