Tencent/WeKnora · error

decode qqbot response: %w

Error message

decode qqbot response: %w

What it means

The QQ bot API returned a 2xx status but the body could not be decoded into the expected response struct. doJSON wraps the json.Decoder error with this message so the root JSON parse cause is preserved.

Source

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

			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()

	body := map[string]string{
		"appId":        c.appID,
		"clientSecret": c.clientSecret,
	}
	var result tokenResponse

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Log the raw response body to see what was actually returned
  2. Check for a proxy/CDN intercepting the request and bypass it
  3. Upgrade the library if the QQ API response schema changed
  4. Retry the request — transient truncation can produce this

Example fix

// before
if err := json.NewDecoder(resp.Body).Decode(out); err != nil { return err } // opaque
// after
body, _ := io.ReadAll(resp.Body)
if err := json.Unmarshal(body, out); err != nil {
    return fmt.Errorf("decode qqbot response: %w; body=%s", err, body)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify endpoint reachability and that it returns JSON before decoding
resp, _ := http.Get(apiBase + "/gateway")
ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "application/json") {
    return fmt.Errorf("unexpected content-type %q (proxy error page?)", ct)
}

Try / catch

if err := json.NewDecoder(resp.Body).Decode(out); err != nil {
    body, _ := io.ReadAll(io.MultiReader(...)) // capture body for diagnostics
    return fmt.Errorf("decode qqbot response: %w", err)
}

Prevention

When it happens

Trigger: GatewayURL, sendText, or AccessToken receives a 2xx response whose body is HTML (proxy error page), truncated, empty, or whose shape changed.

Common situations: Corporate proxy/gateway returning HTML with 200; QQ API response schema drift; interrupted connection truncating the body; hitting a wrong endpoint that returns 200 with a different payload.

Related errors


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