Tencent/WeKnora · error

qqbot api %s %s failed: %s

Error message

qqbot api %s %s failed: %s

What it means

doJSON treats any HTTP status outside 200-299 from the QQ bot API as a failure and surfaces method, URL, and the status line. This is the client's generic non-2xx API error path used by GatewayURL, sendText, and AccessToken.

Source

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

		return err
	}
	req.Header.Set("Content-Type", "application/json")
	if !strings.Contains(url, "getAppAccessToken") {
		token, err := c.AccessToken(ctx)
		if err != nil {
			return err
		}
		req.Header.Set("Authorization", "QQBot "+token)
	}

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return fmt.Errorf("qqbot api %s %s failed: %s", method, url, resp.Status)
	}
	if out == nil {
		return nil
	}
	if err := json.NewDecoder(resp.Body).Decode(out); err != nil {
		return fmt.Errorf("decode qqbot response: %w", err)
	}
	return nil
}

func (c *Client) AccessToken(ctx context.Context) (string, error) {
	c.mu.Lock()
	if c.accessToken != "" && time.Until(c.expiresAt) > time.Minute {
		token := c.accessToken
		c.mu.Unlock()
		return token, nil
	}
	c.mu.Unlock()

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Read the status code in the message: fix auth for 401 (check AppID/AppSecret), back off for 429, retry later for 5xx
  2. Verify the access token is fresh and credentials are correct
  3. Check QQ bot API status/incidents and add retry with backoff for transient codes

Example fix

// before
client.GatewayURL(ctx) // panics on 401 without handling
// after
u, err := client.GatewayURL(ctx)
if err != nil {
    var respErr *apiStatusError // wrap or parse status from message
    log.Printf("qqbot api unavailable: %v", err)
    return retryWithBackoff(...)
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: verify credentials/token before message sends
if _, err := client.AccessToken(ctx); err != nil {
    return fmt.Errorf("credentials invalid, skipping send: %w", err)
}

Try / catch

u, err := client.GatewayURL(ctx)
if err != nil {
    if strings.Contains(err.Error(), "failed: 429") {
        return retryWithBackoff(ctx, func() error { _, err = client.GatewayURL(ctx); return err })
    }
    return err
}

Prevention

When it happens

Trigger: Any QQ bot API call (gateway discovery, sending a message, fetching an app access token) returns 4xx/5xx, e.g. 401 from an invalid/expired appID-token pair, 429 rate limit, or 5xx outage.

Common situations: Wrong AppID/AppSecret; token caching logic racing expiry; QQ API rate limiting; QQ platform outage; network proxy returning 502.

Related errors


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