{"record":{"id":"88b23851de085670","repo":"HKUDS/Vibe-Trading","slug":"signal-sse-stream-closed-by-remote-endpoint","errorCode":null,"errorMessage":"Signal SSE stream closed by remote endpoint","messagePattern":"Signal SSE stream closed by remote endpoint","errorType":"error_code","errorClass":"ConnectionError","httpStatus":null,"severity":"warning","filePath":"agent/src/channels/signal.py","lineNumber":649,"sourceCode":"                                    self.logger.warning(\n                                        \"Invalid JSON in SSE buffer: {}, data: {}\",\n                                        e,\n                                        data_str[:200],\n                                    )\n                                finally:\n                                    event_buffer = []\n\n                        # \"data:\" line - accumulate it\n                        elif line.startswith(\"data:\"):\n                            # SSE spec: strip one optional leading space after \"data:\".\n                            event_buffer.append(line[6:] if line[5:6] == \" \" else line[5:])\n\n                        # \"event:\" line - just log it (we only care about data)\n                        elif line.startswith(\"event:\"):\n                            pass  # Ignore event type for now\n\n                if self._running:\n                    raise ConnectionError(\"Signal SSE stream closed by remote endpoint\")\n\n        except asyncio.CancelledError:\n            self.logger.info(\"SSE receive loop cancelled\")\n            raise\n        except Exception as e:\n            self.logger.error(\"Error in SSE receive loop: {}\", e)\n            raise\n\n    @asynccontextmanager\n    async def _safe_handle(self, action: str, payload: Any = None) -> AsyncIterator[None]:\n        \"\"\"Swallow and log any exception from a top-level handler block.\n\n        Logs `self.logger.error` with the action name, the exception, and a\n        bounded ``repr`` of the offending payload so the offending input is\n        recoverable from logs without having to correlate by timestamp.\n        \"\"\"\n        try:\n            yield","sourceCodeStart":631,"sourceCodeEnd":667,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/channels/signal.py#L631-L667","documentation":"The SSE stream from signal-cli terminated cleanly (stream context exited) while the channel was still running, treated as a remote disconnect and trigger for reconnect.","triggerScenarios":"signal-cli shutting down or dropping the event stream during normal operation; the loop re-establishes the connection after this raise.","commonSituations":"signal-cli restarts (e.g. after link/registration changes), idle connection reaping by middleboxes.","solutions":["Treat as transient: ensure the supervisor/reconnect loop is active","Check why signal-cli dropped the stream (logs, OOM, restart policy)","If behind a proxy, raise its read/idle timeouts for SSE"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"except ConnectionError as e:\n    if 'closed by remote' in str(e):\n        log.info('Stream closed; reconnecting')  # loop handles it","preventionTips":["Expect occasional SSE drops; rely on the reconnect loop","Alert only on repeated rapid reconnects"],"tags":["signal","sse","reconnect"],"backgroundTag":"sse-stream-disconnected","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}