Tencent/WeKnora · error

WeCom bot adapter does not support webhook callbacks

Error message

WeCom bot adapter does not support webhook callbacks

What it means

The WeCom bot WebSocket adapter (WSAdapter) implements the im.Adapter interface, which requires VerifyCallback. Because this adapter receives messages over a persistent WebSocket connection rather than an HTTP webhook, it cannot verify webhook callbacks and always returns this error. It is a deliberate 'unsupported operation' stub, not a transient failure.

Source

Thrown at internal/im/wecom/ws_adapter.go:42

// WSAdapter implements im.Adapter and im.StreamSender for WeCom in WebSocket
// (long connection) mode. It delegates to the WebSocket LongConnClient.
// The webhook methods (VerifyCallback, ParseCallback, HandleURLVerification) are no-ops
// since messages arrive via WebSocket, not HTTP.
type WSAdapter struct {
	client *LongConnClient
}

// NewWSAdapter creates an adapter backed by a WeCom long connection client.
func NewWSAdapter(client *LongConnClient) *WSAdapter {
	return &WSAdapter{client: client}
}

func (a *WSAdapter) Platform() im.Platform {
	return im.PlatformWeCom
}

func (a *WSAdapter) VerifyCallback(c *gin.Context) error {
	return fmt.Errorf("WeCom bot adapter does not support webhook callbacks")
}

func (a *WSAdapter) ParseCallback(c *gin.Context) (*im.IncomingMessage, error) {
	return nil, fmt.Errorf("WeCom bot adapter does not support webhook callbacks")
}

func (a *WSAdapter) HandleURLVerification(c *gin.Context) bool {
	return false
}

func (a *WSAdapter) SendReply(ctx context.Context, incoming *im.IncomingMessage, reply *im.ReplyMessage) error {
	return a.client.SendReply(ctx, incoming, reply)
}

// ── StreamSender implementation ──

func (a *WSAdapter) StartStream(ctx context.Context, incoming *im.IncomingMessage) (string, error) {
	return a.client.StartStream(ctx, incoming)

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Do not route webhook verification to the WS adapter; WeCom bot messages arrive over WebSocket, so remove VerifyCallback handling from its request path.
  2. Register the WS adapter only in the WebSocket message loop and keep webhook routes bound to adapters that implement callback verification (e.g. the corp-app HTTP adapter).
  3. Use HandleURLVerification / VerifyCallback only on adapters whose transport is HTTP; branch on adapter capabilities before calling.

Example fix

// before
err := wsAdapter.VerifyCallback(c) // always fails
// after
if _, ok := adapter.(im.WebhookVerifier); ok {
    err = adapter.VerifyCallback(c)
} else {
    // handle via WebSocket path
}
Defensive patterns

Strategy: validation

Validate before calling

if verifier, ok := adapter.(interface{ VerifyCallback(*gin.Context) error }); ok && supportsWebhook(adapter.Platform()) {
    err = verifier.VerifyCallback(c)
}

Type guard

func supportsWebhookVerify(a im.Adapter) bool {
    _, ok := a.(interface{ VerifyCallback(*gin.Context) error });
    return ok && !isWecomWSAdapter(a)
}

Try / catch

if err := adapter.VerifyCallback(c); err != nil && strings.Contains(err.Error(), "does not support webhook callbacks") {
    c.Status(http.StatusNotImplemented)
    return
}

Prevention

When it happens

Trigger: Calling VerifyCallback on a *im.WSAdapter obtained from the WeCom bot adapter, typically from a shared HTTP webhook route that dispatches to adapters generically.

Common situations: Reusing a webhook handler built for the WeCom corp-app (HTTP callback) adapter or another IM platform and pointing it at the WeCom bot WS adapter; registering the WS adapter in an HTTP callback router; assuming all Platform() values support webhook verification.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/a3f177d76b639bba. Report an issue: GitHub.