From d7318776668f508a0475206051aebc6512527c6e Mon Sep 17 00:00:00 2001 From: Omar B Date: Sat, 9 May 2026 04:17:53 -0400 Subject: [PATCH 1/2] fix: handle Discord typing indicator 429 gracefully MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The typing indicator loop (send_typing) ran every 8s and died on any exception, including Discord 429 rate limits. Once a 429 killed the loop, the indicator never restarted — and the raw exception bounce could cascade into broader gateway instability. Changes: - Bump sleep interval from 8s to 12s (typing light lasts ~10s) - On 429: extract retry_after, log a warning, sleep the backoff, and continue the loop - On non-rate-limit errors: log debug and return (unchanged behaviour) --- gateway/platforms/discord.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/gateway/platforms/discord.py b/gateway/platforms/discord.py index 32a0026973ae..0d64b24d7e4b 100644 --- a/gateway/platforms/discord.py +++ b/gateway/platforms/discord.py @@ -2706,8 +2706,13 @@ async def send_typing(self, chat_id: str, metadata=None) -> None: Discord's TYPING_START gateway event is unreliable in DMs for bots. Instead, start a background loop that hits the typing endpoint every - 8 seconds (typing indicator lasts ~10s). The loop is cancelled when + 12 seconds (typing indicator lasts ~10s). The loop is cancelled when stop_typing() is called (after the response is sent). + + Rate-limit handling: if a 429 is encountered, the loop logs a + warning, sleeps for the ``retry_after`` duration (or a sensible + default), and continues — it does NOT die on a single rate-limit + hit. Only CancelledError (from stop_typing) stops the loop. """ if not self._client: return @@ -2727,9 +2732,22 @@ async def _typing_loop() -> None: except asyncio.CancelledError: return except Exception as e: - logger.debug("Discord typing indicator failed for %s: %s", chat_id, e) - return - await asyncio.sleep(8) + # Don't die on 429 — backoff and continue + retry_after = self._extract_discord_retry_after(e) + if retry_after is not None: + logger.warning( + "Typing indicator rate-limited for %s; retrying in %.1fs", + chat_id, retry_after, + ) + else: + logger.debug( + "Discord typing indicator failed for %s: %s", + chat_id, e, + ) + return + await asyncio.sleep(retry_after) + continue + await asyncio.sleep(12) except asyncio.CancelledError: pass finally: From 099676fb8229a81f6ed3bd9705cac0c4027ad6af Mon Sep 17 00:00:00 2001 From: teknium1 <127238744+teknium1@users.noreply.github.com> Date: Wed, 20 May 2026 22:57:25 -0700 Subject: [PATCH 2/2] chore: add nycomar to AUTHOR_MAP --- scripts/release.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/release.py b/scripts/release.py index eaae1c576e8d..32a345e349ce 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -59,6 +59,7 @@ "altriatree@gmail.com": "TruaShamu", "m@mobrienv.dev": "mikeyobrien", "saeed919@pm.me": "falasi", + "omar@techdeveloper.site": "nycomar", "qiyin.zuo@pcitc.com": "qiyin-code", "mr.aashiz@gmail.com": "aashizpoudel", "70629228+shaun0927@users.noreply.github.com": "shaun0927",