From 2f8aa1b8d9fe327bfe19fbc6daad412675843837 Mon Sep 17 00:00:00 2001 From: JexLau Date: Thu, 19 Feb 2026 05:36:00 +0800 Subject: [PATCH] fix: add goroutine safety to Discord typing indicator - Add 5-minute timeout as safety net to prevent indefinite goroutine leaks when agent produces no outbound message (empty response, panic, etc.) - Listen on c.ctx.Done() so goroutine exits when channel context is cancelled - Log ChannelTyping() errors at debug level for diagnostics (rate limits, session closed) Co-Authored-By: Claude Sonnet 4.6 --- pkg/channels/discord.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pkg/channels/discord.go b/pkg/channels/discord.go index 8eb0c0ef9..9ddec662c 100644 --- a/pkg/channels/discord.go +++ b/pkg/channels/discord.go @@ -295,15 +295,24 @@ func (c *DiscordChannel) startTyping(chatID string) { c.typingMu.Unlock() go func() { - c.session.ChannelTyping(chatID) + if err := c.session.ChannelTyping(chatID); err != nil { + logger.DebugCF("discord", "ChannelTyping error", map[string]interface{}{"chatID": chatID, "err": err}) + } ticker := time.NewTicker(8 * time.Second) defer ticker.Stop() + timeout := time.After(5 * time.Minute) for { select { case <-stop: return + case <-timeout: + return + case <-c.ctx.Done(): + return case <-ticker.C: - c.session.ChannelTyping(chatID) + if err := c.session.ChannelTyping(chatID); err != nil { + logger.DebugCF("discord", "ChannelTyping error", map[string]interface{}{"chatID": chatID, "err": err}) + } } } }()