chenhg5/cc-connect · error

qqbot: token refresh on 401: %w

Error message

qqbot: token refresh on 401: %w

What it means

When the QQ API answers 401 (stale/expired cached token), apiRequestJSON attempts one recovery: it calls p.refreshToken() to force a new token. If that refresh itself fails, this error wraps the refresh failure. The original 401 never reaches the caller as such — the caller only sees that the recovery path broke.

Source

Thrown at platform/qqbot/qqbot.go:335

	}

	req, err := http.NewRequest(method, url, bodyReader)
	if err != nil {
		return err
	}
	req.Header.Set("Authorization", "QQBot "+token)
	req.Header.Set("Content-Type", "application/json")

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

	// Retry once on 401
	if resp.StatusCode == http.StatusUnauthorized {
		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)
		}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Fix the underlying refresh failure: verify appId/appSecret are current (see wrapped error).
  2. Restart cc-connect to clear in-memory token state, then retry.
  3. Check QQ Open Platform status — a 401 followed by refresh failure often indicates an auth-service outage.
  4. Confirm host clock is synchronized (NTP) since token issuance validates timestamps.
  5. If persistent, re-create credentials in the QQ console and update config.toml.
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: force a token fetch at startup so bad credentials fail fast
if _, err := p.getAccessToken(); err != nil {
    return fmt.Errorf("qqbot: startup token check failed: %w", err)
}

Try / catch

if err := send(); err != nil {
    if strings.Contains(err.Error(), "token refresh on 401") {
        slog.Error("qqbot credentials rejected; verify appId/appSecret", "err", err)
        // backoff and alert; retrying won't help until creds are fixed
    }
}

Prevention

When it happens

Trigger: The API returned HTTP 401 and the subsequent p.refreshToken() call failed — typically because the token endpoint rejected the new token request (bad AppSecret) or was unreachable at that moment.

Common situations: Token cache invalidated server-side (credential rotation, app suspension) while the secret in config is stale; QQ Open Platform outage coinciding with token expiry; clock skew making token issuance fail.

Related errors


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