Tencent/WeKnora · error

unsupported qqbot mode: %s (only websocket is supported)

Error message

unsupported qqbot mode: %s (only websocket is supported)

What it means

The QQ bot adapter factory in internal/im/qqbot/factory.go only supports the 'websocket' connection mode. The channel's configured mode is resolved via im.ResolveMode (default 'websocket'), and if it resolves to anything else (e.g. 'webhook'), construction of the adapter fails immediately with this wrapped error.

Source

Thrown at internal/im/qqbot/factory.go:20

import (
	"context"
	"fmt"

	"github.com/Tencent/WeKnora/internal/im"
	"github.com/Tencent/WeKnora/internal/logger"
)

func NewFactory() im.AdapterFactory {
	return func(factoryCtx context.Context, channel *im.IMChannel, msgHandler func(context.Context, *im.IncomingMessage) error) (im.Adapter, context.CancelFunc, error) {
		creds, err := im.ParseCredentials(channel.Credentials)
		if err != nil {
			return nil, nil, fmt.Errorf("parse qqbot credentials: %w", err)
		}

		mode := im.ResolveMode(channel, "websocket")
		if mode != "websocket" {
			return nil, nil, fmt.Errorf("unsupported qqbot mode: %s (only websocket is supported)", mode)
		}

		client, err := NewClient(
			im.GetString(creds, "app_id"),
			im.GetString(creds, "client_secret"),
			im.GetString(creds, "api_base_url"),
			im.GetString(creds, "gateway_url"),
		)
		if err != nil {
			return nil, nil, err
		}

		longConn := NewLongConnClient(client, msgHandler)
		wsCtx, wsCancel := context.WithCancel(context.Background())
		go func() {
			if err := longConn.Start(wsCtx); err != nil && wsCtx.Err() == nil {
				logger.Errorf(context.Background(), "[IM] QQBot long connection stopped for channel %s: %v", channel.ID, err)
			}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Set the channel's mode to "websocket" (or omit it to get the websocket default)
  2. Remove any webhook URL/mode fields copied from other platform configs
  3. If webhook mode is truly needed, verify the library version supports it for QQ — it does not, so switch platform or implement a websocket-only setup

Example fix

// before
{"platform":"qqbot","mode":"webhook","credentials":{...}}
// after
{"platform":"qqbot","mode":"websocket","credentials":{"app_id":"...","client_secret":"..."}}
Defensive patterns

Strategy: validation

Validate before calling

mode := im.ResolveMode(channel, "websocket")
if mode != "websocket" {
    return fmt.Errorf("qqbot channel %s requires websocket mode, got %q", channel.ID, mode)
}

Prevention

When it happens

Trigger: Creating/starting a QQ channel whose credentials resolve a mode other than 'websocket' — e.g. setting mode=webhook in the channel config or a credentials key that ResolveMode reads as a non-websocket mode.

Common situations: Copying a Telegram/Slack channel config (which supports webhook) and reusing it for QQ; a config migration that sets a webhook URL for QQ; typos in the mode field that resolve to a non-websocket string.

Related errors


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