From 9247746a79d61052c5f889fb7a8a1c19a888040b Mon Sep 17 00:00:00 2001 From: goodboy Date: Thu, 26 Feb 2026 17:46:54 -0500 Subject: [PATCH] Handle unknown order statuses in `.ib.broker` Add fallback handling for unknown IB order status strings to avoid crashes when IB returns unexpected status values. Deats, - add `'ValidationError': 'error'` mapping to `_statuses` dict. - use `.get()` with `'error'` default instead of direct dict lookup for `status.status`. - add `elif status_str == 'error'` block to log unknown status values. - add type annots to `event_name` and `item` in `deliver_trade_events()` loop. Also, - reformat log msg in `deliver_trade_events()` to multiline. - drop extra conditional in `if status_str == 'filled'` check. (this commit msg was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code --- piker/brokers/ib/broker.py | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/piker/brokers/ib/broker.py b/piker/brokers/ib/broker.py index 37b6f602..af6af5e8 100644 --- a/piker/brokers/ib/broker.py +++ b/piker/brokers/ib/broker.py @@ -991,6 +991,9 @@ _statuses: dict[str, str] = { # TODO: see a current ``ib_insync`` issue around this: # https://github.com/erdewit/ib_insync/issues/363 'Inactive': 'pending', + + # XXX, uhh wut the heck is this? + 'ValidationError': 'error', } _action_map = { @@ -1063,8 +1066,19 @@ async def deliver_trade_events( # TODO: for some reason we can receive a ``None`` here when the # ib-gw goes down? Not sure exactly how that's happening looking # at the eventkit code above but we should probably handle it... + event_name: str + item: ( + Trade + |tuple[Trade, Fill] + |CommissionReport + |IbPosition + |dict + ) async for event_name, item in trade_event_stream: - log.info(f'Relaying `{event_name}`:\n{pformat(item)}') + log.info( + f'Relaying {event_name!r}:\n' + f'{pformat(item)}\n' + ) match event_name: case 'orderStatusEvent': @@ -1075,11 +1089,12 @@ async def deliver_trade_events( trade: Trade = item reqid: str = str(trade.order.orderId) status: OrderStatus = trade.orderStatus - status_str: str = _statuses[status.status] + status_str: str = _statuses.get( + status.status, + 'error', + ) remaining: float = status.remaining - if ( - status_str == 'filled' - ): + if status_str == 'filled': fill: Fill = trade.fills[-1] execu: Execution = fill.execution @@ -1110,6 +1125,12 @@ async def deliver_trade_events( # all units were cleared. status_str = 'closed' + elif status_str == 'error': + log.error( + f'IB reported error status for order ??\n' + f'{status.status!r}\n' + ) + # skip duplicate filled updates - we get the deats # from the execution details event msg = BrokerdStatus(