QuantConnect/Lean · error · AssertionError

Expected order ticket in order event to not be null

Error message

Expected order ticket in order event to not be null

What it means

OrderTicketAssignmentDemoAlgorithm places asynchronous market orders and demonstrates that you cannot rely on the return value being assigned to self.ticket before order events fire. In on_order_event it reads order_event.ticket (the ticket the engine attaches to the event) and asserts it is not None. A None ticket means the engine failed to associate the OrderTicket with the event for that order — a regression in Lean's order-event/ticket wiring.

Source

Thrown at Algorithm.Python/OrderTicketAssignmentDemoAlgorithm.py:44

        self._symbol = self.add_equity("SPY").symbol

        self.trade_count = 0
        self.consolidate(self._symbol, timedelta(hours=1), self.hour_consolidator)

    def hour_consolidator(self, bar: TradeBar):
        # Reset self.ticket to None on each new bar
        self.ticket = None
        self.ticket = self.market_order(self._symbol, 1, asynchronous=True)
        self.debug(f"{self.time}: Buy: Price {bar.price}, order_id: {self.ticket.order_id}")
        self.trade_count += 1

    def on_order_event(self, order_event: OrderEvent):
        # We cannot access self.ticket directly because it is assigned asynchronously:
        # this order event could be triggered before self.ticket is assigned.
        ticket = order_event.ticket
        if ticket is None:
            raise AssertionError("Expected order ticket in order event to not be null")
        if order_event.status == OrderStatus.SUBMITTED and self.ticket is not None:
            raise AssertionError("Field self.ticket not expected no be assigned on the first order event")

        self.debug(ticket.to_string())

    def on_end_of_algorithm(self):
        # Just checking that orders were placed
        if not self.portfolio.invested or self.trade_count != self.transactions.orders_count:
            raise AssertionError(f"Expected the portfolio to have holdings and to have {self.trade_count} trades, but had {self.transactions.orders_count}")

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Confirm the order was user-submitted (via market_order/asynchronous=True); for internal orders, guard with `if order_event.ticket is None: return`.
  2. If you modified Lean, ensure OrderEvent.Ticket is populated for every user order event path.
  3. Use order_event.order_id to look up the ticket via self.transactions.get_order_by_id(...) as a fallback.
  4. Filter out non-user order events (e.g. check order_event.ticket is not None only for OrderStatus you expect).

Example fix

# before
ticket = order_event.ticket
if ticket is None:
    raise AssertionError('Expected order ticket in order event to not be null')
# after: tolerate internal orders, look up by id
ticket = order_event.ticket or self.transactions.get_order_ticket(order_event.order_id)
if ticket is None:
    return  # internal/automatic order without a user ticket
Defensive patterns

Strategy: type-guard

Validate before calling

# Prefer the event's ticket; fall back to lookup by order id
ticket = order_event.ticket or self.transactions.get_order_ticket(order_event.order_id)
if ticket is None:
    return  # internal/automatic order without a user ticket

Type guard

def has_ticket(order_event) -> bool:
    return order_event.ticket is not None

Prevention

When it happens

Trigger: An OrderEvent arrives in on_order_event whose .ticket property is None. This happens if the engine does not set the ticket reference on the event, if the order was generated internally (e.g. margin call) without a ticket, or after a refactor of OrderEvent.Ticket population.

Common situations: A Lean change decoupling OrderEvent from its OrderTicket; internal/automatic orders (liquidations, margin calls, option assignment/exercise) that legitimately lack a user ticket; a brokerage event path that bypasses ticket assignment.

Related errors


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