Fix KeyError crash when a websocket subscription fails - #373
Fix KeyError crash when a websocket subscription fails#373massimiliano1991 wants to merge 1 commit into
Conversation
|
I am not sure what exactly this PR seeks to achieve. There should be no legitimate workflow where the application ends up listening to the wrong topic, ever. If there is such workflow, it should be fixed by the developer, as it's an incorrect usage of pybit. |
|
Agreed — a rejected subscribe means the developer did something wrong, and this PR does not try to make that legitimate. It only changes what happens at that moment. Today the failure branch itself crashes: If you'd rather fail hard on a rejected subscribe, happy to change the fix to raise a clear exception instead — the goal is only surfacing |
Problem
When the server rejects a subscription (
success: false),_process_subscription_messagecallsself._pop_callback(topic[0]). Buttopicis either the raw JSON subscription message (req_id branch) or a topic string (fallback branch), sotopic[0]is'{'or the topic's first character — and_pop_callbackraisesKeyError.Because
KeyErroris not one of the disconnection errors that_on_errortolerates, the exception is re-raised and the whole websocket dies. So one rejected subscription (e.g. a mistyped topic) kills the connection with a crypticKeyError: '{'instead of the error log the code intends to produce.Reproduce against current master (no network needed):
Two side effects of the same path: the failed subscription stays in
self.subscriptions, so a reconnect replays it (and fails again), and the callback entry is never removed, so re-subscribing to the same topic raises "You have already subscribed to this topic".Fix
On failure, resolve the
argslist of the stored subscription message, pop each affected callback that exists, and drop the failed subscription fromself.subscriptionsso a reconnect does not replay it. The success debug log now shows the topics instead of the raw JSON message. No behaviour change on the success path.Tests
4 regression tests added (failure with req_id, failure without req_id, multi-symbol failure, success path unchanged). Full suite: 48/48 passing.