Tencent/WeKnora · error

gateway_url must use wss

Error message

gateway_url must use wss

What it means

Validation helper validateGatewayURL rejects a configured QQ bot gateway_url whose scheme is not wss — the gateway requires secure WebSocket. Fires only when an override is provided with ws/https or another scheme.

Source

Thrown at internal/im/qqbot/client.go:101

	if u.Scheme != "http" && u.Scheme != "https" {
		return fmt.Errorf("invalid qqbot api_base_url: must use http or https")
	}
	if err := secutils.ValidateURLForSSRF(raw); err != nil {
		return fmt.Errorf("invalid qqbot api_base_url: %w (for private deployments, add the hostname to SSRF_WHITELIST)", err)
	}
	return nil
}

func validateGatewayURL(raw string) error {
	if strings.TrimSpace(raw) == "" {
		return nil
	}
	u, err := url.Parse(raw)
	if err != nil || u.Host == "" {
		return fmt.Errorf("gateway_url must be a valid wss URL")
	}
	if u.Scheme != "wss" {
		return fmt.Errorf("gateway_url must use wss")
	}
	checkURL := *u
	checkURL.Scheme = "https"
	if err := secutils.ValidateURLForSSRF(checkURL.String()); err != nil {
		return fmt.Errorf(
			"gateway_url failed SSRF validation: %w (for private deployments, add the hostname to SSRF_WHITELIST)",
			err,
		)
	}
	return nil
}

func (c *Client) SendC2CMessage(ctx context.Context, openID, content, msgID string) error {
	path := fmt.Sprintf("/v2/users/%s/messages", openID)
	return c.sendText(ctx, path, content, msgID)
}

func (c *Client) SendGroupMessage(ctx context.Context, groupOpenID, content, msgID string) error {

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Change the scheme to wss:// (e.g. wss://api.sgroup.qq.com/websocket)
  2. Keep the HTTPS API endpoint in api_base_url, not gateway_url
  3. For local testing against a private gateway, use wss with a locally trusted certificate

Example fix

// before
cfg.GatewayURL = "https://api.sgroup.qq.com/websocket"
// after
cfg.GatewayURL = "wss://api.sgroup.qq.com/websocket"
Defensive patterns

Strategy: validation

Validate before calling

func isWSS(raw string) bool {
    p, err := url.Parse(strings.TrimSpace(raw))
    return err == nil && p.Host != "" && p.Scheme == "wss"
}
if !isWSS(cfg.GatewayURL) { return errors.New("gateway_url must start with wss://") }

Try / catch

client, err := NewClient(cfg)
if err != nil && strings.Contains(err.Error(), "gateway_url must use wss") {
    return fmt.Errorf("gateway scheme must be wss://: %w", err)
}

Prevention

When it happens

Trigger: NewClient or GatewayURL is given a gateway_url whose parsed scheme is not "wss", e.g. http:// or ws://.

Common situations: Copying an HTTPS API URL into the gateway_url field; using insecure ws:// for local testing; older configs written before wss was enforced.

Related errors


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