From 62f59f76e3aaea62e7e9066926db010366af1ca5 Mon Sep 17 00:00:00 2001 From: Hoshina Date: Sat, 28 Feb 2026 21:30:58 +0800 Subject: [PATCH 1/2] fix(wecom): use channel context instead of HTTP request context for async message processing The HTTP request context is canceled as soon as the handler returns the response, causing PublishInbound to fail with "context canceled" when processMessage runs asynchronously in a goroutine. Use the channel's long-lived context (c.ctx) instead. --- pkg/channels/wecom/app.go | 5 +++-- pkg/channels/wecom/bot.go | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/channels/wecom/app.go b/pkg/channels/wecom/app.go index 42a74e8c9..3a25e12e1 100644 --- a/pkg/channels/wecom/app.go +++ b/pkg/channels/wecom/app.go @@ -567,8 +567,9 @@ func (c *WeComAppChannel) handleMessageCallback(ctx context.Context, w http.Resp return } - // Process the message with context - go c.processMessage(ctx, msg) + // Process the message with the channel's long-lived context (not the HTTP + // request context, which is canceled as soon as we return the response). + go c.processMessage(c.ctx, msg) // Return success response immediately // WeCom App requires response within configured timeout (default 5 seconds) diff --git a/pkg/channels/wecom/bot.go b/pkg/channels/wecom/bot.go index 4c576b84b..d904389f6 100644 --- a/pkg/channels/wecom/bot.go +++ b/pkg/channels/wecom/bot.go @@ -292,8 +292,9 @@ func (c *WeComBotChannel) handleMessageCallback(ctx context.Context, w http.Resp return } - // Process the message asynchronously with context - go c.processMessage(ctx, msg) + // Process the message with the channel's long-lived context (not the HTTP + // request context, which is canceled as soon as we return the response). + go c.processMessage(c.ctx, msg) // Return success response immediately // WeCom Bot requires response within configured timeout (default 5 seconds) From 8e06e2adbd08395f7cce100e164c314ec9a37a68 Mon Sep 17 00:00:00 2001 From: Hoshina Date: Sat, 28 Feb 2026 21:45:05 +0800 Subject: [PATCH 2/2] fix(wecom): initialize context in constructors to prevent nil panic in tests The ctx field was only set in Start(), so tests calling handleMessageCallback without Start() caused a nil pointer dereference in MessageBus.PublishInbound. --- pkg/channels/wecom/app.go | 3 +++ pkg/channels/wecom/bot.go | 3 +++ 2 files changed, 6 insertions(+) diff --git a/pkg/channels/wecom/app.go b/pkg/channels/wecom/app.go index 3a25e12e1..771603f3e 100644 --- a/pkg/channels/wecom/app.go +++ b/pkg/channels/wecom/app.go @@ -129,9 +129,12 @@ func NewWeComAppChannel(cfg config.WeComAppConfig, messageBus *bus.MessageBus) ( channels.WithReasoningChannelID(cfg.ReasoningChannelID), ) + ctx, cancel := context.WithCancel(context.Background()) return &WeComAppChannel{ BaseChannel: base, config: cfg, + ctx: ctx, + cancel: cancel, processedMsgs: make(map[string]bool), }, nil } diff --git a/pkg/channels/wecom/bot.go b/pkg/channels/wecom/bot.go index d904389f6..e99c710ef 100644 --- a/pkg/channels/wecom/bot.go +++ b/pkg/channels/wecom/bot.go @@ -93,9 +93,12 @@ func NewWeComBotChannel(cfg config.WeComConfig, messageBus *bus.MessageBus) (*We channels.WithReasoningChannelID(cfg.ReasoningChannelID), ) + ctx, cancel := context.WithCancel(context.Background()) return &WeComBotChannel{ BaseChannel: base, config: cfg, + ctx: ctx, + cancel: cancel, processedMsgs: make(map[string]bool), }, nil }