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
- Fix the underlying refresh failure: verify appId/appSecret are current (see wrapped error).
- Restart cc-connect to clear in-memory token state, then retry.
- Check QQ Open Platform status — a 401 followed by refresh failure often indicates an auth-service outage.
- Confirm host clock is synchronized (NTP) since token issuance validates timestamps.
- 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
- Run a startup token pre-flight to catch bad credentials immediately.
- Keep host clock synchronized via NTP.
- Alert on 401+refresh-failure pairs — they indicate rejected credentials, not transient auth.
- Re-verify secrets after any rotation in the QQ Open Platform console.
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
- get access token: %w
- dingtalk: get access token for proactive send: %w
- %s: %s failed after token refresh attempt: %w (original erro
- qqbot: failed to get access token: %w
- qqbot: get token: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/e996d962f5566970.
Report an issue: GitHub.