From 2eccbc7279595ee8e93d21ef14f55f6c8508b8e7 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Tue, 21 Apr 2026 20:54:00 +0300 Subject: [PATCH] fix(webhook): avoid MissingGreenlet on expired ORM instance after commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Telegram webhook handler crashed with sqlalchemy.exc.MissingGreenlet when processing any incoming message after committing the chat row: TelegramChat.bot_id == bot.id ^^^^^^ MissingGreenlet: greenlet_spawn has not been called AsyncSession expires all instances on commit. Accessing bot.id/bot.token after that triggers implicit lazy-load I/O from a sync attribute getter, which can't enter the greenlet dispatcher → crash. Fix: snapshot bot.id + bot.token to locals before commit, refresh the ORM instance after a successful commit so handle_command() can still use it, and route the remaining call sites through the snapshot variables. --- .../src/notify_bridge_server/commands/webhook.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/server/src/notify_bridge_server/commands/webhook.py b/packages/server/src/notify_bridge_server/commands/webhook.py index da33a29..b0af020 100644 --- a/packages/server/src/notify_bridge_server/commands/webhook.py +++ b/packages/server/src/notify_bridge_server/commands/webhook.py @@ -71,9 +71,15 @@ async def telegram_webhook( # Auto-persist chat from incoming message from_user = message.get("from", {}) msg_language = from_user.get("language_code", "") + # Snapshot bot identity before commit — AsyncSession expires instances + # on commit, and implicit lazy-load of `bot.id` / `bot.token` later would + # raise sqlalchemy.exc.MissingGreenlet. + bot_id = bot.id + bot_token = bot.token try: - await save_chat_from_webhook(session, bot.id, chat_info, language_code=msg_language) + await save_chat_from_webhook(session, bot_id, chat_info, language_code=msg_language) await session.commit() + await session.refresh(bot) except Exception: _LOGGER.warning("Failed to auto-save chat %s", chat_id, exc_info=True) @@ -81,7 +87,7 @@ async def telegram_webhook( if text.startswith("/"): chat_row = (await session.exec( select(TelegramChat).where( - TelegramChat.bot_id == bot.id, + TelegramChat.bot_id == bot_id, TelegramChat.chat_id == chat_id, ) )).first() @@ -93,9 +99,9 @@ async def telegram_webhook( if responses: for resp in responses: if resp.text: - await send_reply(bot.token, chat_id, resp.text, reply_to_message_id=message_id) + await send_reply(bot_token, chat_id, resp.text, reply_to_message_id=message_id) if resp.media: - await send_media_group(bot.token, chat_id, resp.media, reply_to_message_id=message_id) + await send_media_group(bot_token, chat_id, resp.media, reply_to_message_id=message_id) return {"ok": True} return {"ok": True, "skipped": "not_a_command"}