chenhg5/cc-connect · error

qqbot: api retry failed: %w

Error message

qqbot: api retry failed: %w

What it means

On the 401-retry path, if the retried HTTP request fails at the transport level (core.HTTPClient.Do returns an error), this wrapped error is returned. Same causes as the initial request failure (DNS, connection, timeout), just occurring on the second attempt after a token refresh.

Source

Thrown at platform/qqbot/qqbot.go:352

		if err := p.refreshToken(); err != nil {
			return fmt.Errorf("qqbot: token refresh on 401: %w", err)
		}
		token, _ = p.getAccessToken()

		if body != nil {
			data, _ := json.Marshal(body)
			bodyReader = bytes.NewReader(data)
		}
		req2, err := http.NewRequest(method, url, bodyReader)
		if err != nil {
			return fmt.Errorf("qqbot: build retry request: %w", err)
		}
		req2.Header.Set("Authorization", "QQBot "+token)
		req2.Header.Set("Content-Type", "application/json")

		resp2, err := core.HTTPClient.Do(req2)
		if err != nil {
			return fmt.Errorf("qqbot: api retry failed: %w", err)
		}
		defer resp2.Body.Close()

		if resp2.StatusCode >= 300 {
			raw, _ := io.ReadAll(resp2.Body)
			return fmt.Errorf("qqbot: api %s %s returned %d (after retry): %s", method, url, resp2.StatusCode, raw)
		}
		if result != nil {
			if err := json.NewDecoder(resp2.Body).Decode(result); err != nil {
				return fmt.Errorf("qqbot: decode response: %w", err)
			}
		}
		return nil
	}

	if resp.StatusCode >= 300 {
		raw, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("qqbot: api %s %s returned %d: %s", method, url, resp.StatusCode, raw)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Treat like the initial transport failure: check connectivity to the QQ API host (curl).
  2. Inspect the wrapped error for timeout vs connection-refused specifics.
  3. Retry the operation after confirming the network is stable.
  4. If uploads are large and timing out, check egress bandwidth/proxy limits.
  5. Ensure no caller context cancels mid-retry.
Defensive patterns

Strategy: retry

Validate before calling

if err := net.DialTimeout("tcp", "api.sgroup.qq.com:443", 5*time.Second); err != nil {
    return fmt.Errorf("network down; qqbot sends will fail: %w", err)
}

Try / catch

var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
    time.Sleep(2 * time.Second)
    return retry() // limited retries with backoff
}

Prevention

When it happens

Trigger: A 401 was received, refreshToken() succeeded, and the rebuilt request to the QQ API failed at transport level — connection drop, timeout, or TLS error on attempt two.

Common situations: Flaky network between host and QQ API where the first failure was auth-related and the second is connectivity; QQ API intermittent outage; long upload bodies timing out on the retry.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/55a7feab186900f7. Report an issue: GitHub.