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
- Set the channel's mode to "websocket" (or omit it to get the websocket default)
- Remove any webhook URL/mode fields copied from other platform configs
- 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
- Always set mode:"websocket" (or omit mode) for qqbot channels
- Never copy webhook config from other platforms to qqbot
- Validate channel configs at creation time, not at adapter start
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
- invalid qqbot api_base_url: %w (for private deployments, add
- gateway_url must be a valid wss URL
- gateway_url must use wss
- parse qqbot credentials: %w
- custom agent configuration is required for agent QA
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/42813444680fea2d.
Report an issue: GitHub.