From 8c55b40b9f383c5e11217cbd6234483a63f597aa Mon Sep 17 00:00:00 2001 From: andienguyen-ecoligo Date: Sat, 21 Feb 2026 12:38:24 -0500 Subject: [PATCH 1/2] fix(qq): make start() long-running per base channel contract QQ channel's start() created a background task and returned immediately, violating the base Channel contract which specifies start() should be "a long-running async task". This caused the gateway to exit prematurely when QQ was the only enabled channel. Now directly awaits _run_bot() to stay alive like other channels. Fixes #894 --- nanobot/channels/qq.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nanobot/channels/qq.py b/nanobot/channels/qq.py index 16cbfb8..a940a75 100644 --- a/nanobot/channels/qq.py +++ b/nanobot/channels/qq.py @@ -71,8 +71,8 @@ class QQChannel(BaseChannel): BotClass = _make_bot_class(self) self._client = BotClass() - self._bot_task = asyncio.create_task(self._run_bot()) logger.info("QQ bot started (C2C private message)") + await self._run_bot() async def _run_bot(self) -> None: """Run the bot connection with auto-reconnect.""" From b53c3d39edece22484568bb1896cbe29bfb3c1ae Mon Sep 17 00:00:00 2001 From: Re-bin Date: Sun, 22 Feb 2026 17:35:53 +0000 Subject: [PATCH 2/2] fix(qq): remove dead _bot_task field and fix stop() to close client --- nanobot/channels/qq.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/nanobot/channels/qq.py b/nanobot/channels/qq.py index a940a75..5352a30 100644 --- a/nanobot/channels/qq.py +++ b/nanobot/channels/qq.py @@ -55,7 +55,6 @@ class QQChannel(BaseChannel): self.config: QQConfig = config self._client: "botpy.Client | None" = None self._processed_ids: deque = deque(maxlen=1000) - self._bot_task: asyncio.Task | None = None async def start(self) -> None: """Start the QQ bot.""" @@ -88,11 +87,10 @@ class QQChannel(BaseChannel): async def stop(self) -> None: """Stop the QQ bot.""" self._running = False - if self._bot_task: - self._bot_task.cancel() + if self._client: try: - await self._bot_task - except asyncio.CancelledError: + await self._client.close() + except Exception: pass logger.info("QQ bot stopped") @@ -130,5 +128,5 @@ class QQChannel(BaseChannel): content=content, metadata={"message_id": data.id}, ) - except Exception as e: - logger.error("Error handling QQ message: {}", e) + except Exception: + logger.exception("Error handling QQ message")