{"record":{"id":"29faf78fd9181cf0","repo":"openai/openai-python","slug":"websocket-connection-closed-with-unsent-messages-29faf7","errorCode":null,"errorMessage":"WebSocket connection closed with unsent messages","messagePattern":"WebSocket connection closed with unsent messages","errorType":"exception","errorClass":"WebSocketConnectionClosedError","httpStatus":null,"severity":"critical","filePath":"src/openai/resources/responses/responses.py","lineNumber":4050,"sourceCode":"        self.response = AsyncResponsesResponseResource(self)\n\n    async def __aiter__(self) -> AsyncIterator[ResponsesServerEvent]:\n        \"\"\"\n        An infinite-iterator that will continue to yield events until\n        the connection is closed.\n        \"\"\"\n        from websockets.exceptions import ConnectionClosedOK, ConnectionClosedError\n\n        while True:\n            try:\n                yield await self.recv()\n            except ConnectionClosedOK:\n                return\n            except ConnectionClosedError as exc:\n                if not await self._reconnect(exc):\n                    unsent = self._send_queue.drain()\n                    if unsent:\n                        raise WebSocketConnectionClosedError(\n                            \"WebSocket connection closed with unsent messages\",\n                            unsent_messages=unsent,\n                        ) from exc\n                    raise\n\n    async def recv(self) -> ResponsesServerEvent:\n        \"\"\"\n        Receive the next message from the connection and parses it into a `ResponsesServerEvent` object.\n\n        Canceling this method is safe. There's no risk of losing data.\n        \"\"\"\n        return self.parse_event(await self.recv_bytes())\n\n    async def recv_bytes(self) -> bytes:\n        \"\"\"Receive the next message from the connection as raw bytes.\n\n        Canceling this method is safe. There's no risk of losing data.\n","sourceCodeStart":4032,"sourceCodeEnd":4068,"githubUrl":"https://github.com/openai/openai-python/blob/9917c6e28e66e90e1227b3d223c06a8c5441515a/src/openai/resources/responses/responses.py#L4032-L4068","documentation":"Raised by the async WebSocket event iterator (__aiter__) when the connection closes with an error, reconnection fails, and there are still unsent messages queued for transmission. The error preserves the unsent messages so callers can recover or re-send them rather than silently dropping output.","triggerScenarios":"Streaming a Responses WebSocket session, sending events while the network drops; ConnectionClosedError occurs, reconnect logic fails, and self._send_queue.drain() returns pending messages, raising WebSocketConnectionClosedError with unsent_messages attached.","commonSituations":"Long-running realtime/streaming sessions over unstable networks (WiFi, mobile, proxies with idle timeouts); sending bursts of input events right as the server or intermediary closes the socket.","solutions":["Catch WebSocketConnectionClosedError and re-send the unsent_messages on a fresh connection","Add keep-alive/ping handling or reduce idle time to avoid mid-stream closes","Implement a reconnect wrapper that re-establishes the session and replays queued output"],"exampleFix":"// before\nasync for event in ws:\n    handle(event)\n// after\ntry:\n    async for event in ws:\n        handle(event)\nexcept WebSocketConnectionClosedError as exc:\n    for msg in exc.unsent_messages:\n        await outbox.put(msg)  # replay after reconnect","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from openai._websocket import WebSocketConnectionClosedError\ntry:\n    async for event in ws:\n        await handle(event)\nexcept WebSocketConnectionClosedError as exc:\n    unsent = exc.unsent_messages\n    ws = await reconnect()\n    for msg in unsent:\n        await ws.send(msg)","preventionTips":["Drain or flush send queues during idle periods","Implement reconnect-with-replay around WebSocket sessions","Monitor connection health and re-send unsent_messages from the exception","Avoid large bursts of sends right before expected disconnects"],"tags":["websocket","responses","streaming","reconnect","network","python"],"backgroundTag":"websocket-connection-closed","analyzedSha":"9917c6e28e66e90e1227b3d223c06a8c5441515a","analyzedAt":"2026-08-28T11:46:34.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}