{"record":{"id":"b1feec0ebbf46ce0","repo":"QuantConnect/Lean","slug":"orderevent-ticket-was-not-set","errorCode":null,"errorMessage":"OrderEvent Ticket was not set","messagePattern":"OrderEvent Ticket was not set","errorType":"exception","errorClass":"AssertionError","httpStatus":null,"severity":"error","filePath":"Algorithm.Python/OrderTicketDemoAlgorithm.py","lineNumber":406,"sourceCode":"        order = self.transactions.get_order_by_id(order_event.order_id)\n        self.log(\"{0}: {1}: {2}\".format(self.time, order.type, order_event))\n\n        if order_event.quantity == 0:\n            raise AssertionError(\"OrderEvent quantity is Not expected to be 0, it should hold the current order Quantity\")\n\n        if order_event.quantity != order.quantity:\n            raise AssertionError(\"OrderEvent quantity should hold the current order Quantity\")\n\n        if (type(order) is LimitOrder and order_event.limit_price == 0 or\n            type(order) is StopLimitOrder and order_event.limit_price == 0):\n            raise AssertionError(\"OrderEvent LimitPrice is Not expected to be 0 for LimitOrder and StopLimitOrder\")\n\n        if type(order) is StopMarketOrder and order_event.stop_price == 0:\n            raise AssertionError(\"OrderEvent StopPrice is Not expected to be 0 for StopMarketOrder\")\n\n        # We can access the order ticket from the order event\n        if order_event.ticket is None:\n            raise AssertionError(\"OrderEvent Ticket was not set\")\n        if order_event.order_id != order_event.ticket.order_id:\n            raise AssertionError(\"OrderEvent.ORDER_ID and order_event.ticket.order_id do not match\")\n\n    def check_pair_orders_for_fills(self, long_order, short_order):\n        if long_order.status == OrderStatus.FILLED:\n            self.log(\"{0}: Cancelling short order, long order is filled.\".format(short_order.order_type))\n            short_order.cancel(\"Long filled.\")\n            return True\n\n        if short_order.status == OrderStatus.FILLED:\n            self.log(\"{0}: Cancelling long order, short order is filled.\".format(long_order.order_type))\n            long_order.cancel(\"Short filled\")\n            return True\n\n        return False\n\n\n    def time_is(self, day, hour, minute):","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/QuantConnect/Lean/blob/d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892/Algorithm.Python/OrderTicketDemoAlgorithm.py#L388-L424","documentation":"Self-test assertion confirming that every OrderEvent delivered to the algorithm carries a back-reference to its OrderTicket. OrderEvent.Ticket is a JsonIgnore, runtime-only property (not serialized) that the transaction processor attaches when the event is dispatched to OnOrderEvent. The assertion fires when that Ticket reference is None/null on arrival.","triggerScenarios":"An OrderEvent reaches on_order_event with order_event.ticket is None. This happens when the event was constructed or deserialized on a path that bypasses the transaction handler's ticket-attachment step (e.g. a manually built event, a replay/deserialized packet, or an engine change that stopped setting Ticket before delivery). Because Ticket is [JsonIgnore], events restored from JSON will never carry it unless re-attached.","commonSituations":"Lean contributors hit this after refactoring the order-event dispatch in the algorithm transaction manager. Users hit it when they synthesize or replay OrderEvent objects (e.g. from a stored result packet) and pass them straight to a handler. It also appears after version upgrades if the dispatch contract for attaching the ticket changed.","solutions":["As an engine regression: ensure the transaction manager sets OrderEvent.Ticket from the OrderTicket before invoking OnOrderEvent.","If you replay/deserialize events: re-attach the ticket via self.transactions.get_order_ticket(order_event.order_id) (or the equivalent order-ticket lookup) before processing.","In your own handler: guard against None and resolve the ticket by order id rather than asserting.","Avoid constructing OrderEvent instances by hand for dispatch; route through the transaction processor so the ticket is attached."],"exampleFix":"# before\nif order_event.ticket is None:\n    raise AssertionError(\"OrderEvent Ticket was not set\")\n\n# after (resolve the ticket when the runtime reference is missing, e.g. on replay)\nticket = order_event.ticket or self.transactions.get_order_ticket(order_event.order_id)\nif ticket is None:\n    raise AssertionError(f\"No OrderTicket found for order id {order_event.order_id}\")","handlingStrategy":"validation","validationCode":"# Resolve the ticket defensively; Ticket is runtime-only and missing on replay/deserialized events\nticket = order_event.ticket\nif ticket is None:\n    ticket = self.transactions.get_order_ticket(order_event.order_id)\nif ticket is None:\n    self.debug(f\"No ticket for order {order_event.order_id}; cannot process event\")\n    return","typeGuard":"def get_event_ticket(algorithm, order_event):\n    \"\"\"Return the OrderTicket for an event, resolving it when the runtime ref is missing.\"\"\"\n    return order_event.ticket or algorithm.transactions.get_order_ticket(order_event.order_id)","tryCatchPattern":null,"preventionTips":["Never assume order_event.ticket is populated; it is JsonIgnore and absent on deserialized events.","When replaying stored events, re-attach tickets via the transaction manager before dispatch.","Route order creation through the transaction processor so the ticket is attached automatically."],"tags":["quantconnect","lean","orders","order-event","order-ticket","regression-test","python"],"backgroundTag":null,"analyzedSha":"d2c3659f877bfc2b5d9dc0fc89a9c7566f45e892","analyzedAt":"2026-08-13T13:52:21.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}