chenhg5/cc-connect · error
qqbot: get token: %w
Error message
qqbot: get token: %w
What it means
This error is raised inside apiRequestJSON when p.getAccessToken() fails before any HTTP request is made. getAccessToken fetches (and caches) the app-wide access token using the configured AppID/AppSecret; failure means credentials are wrong, the token endpoint is unreachable, or the cached token could not be refreshed. All qqbot API calls (sendMessage, uploadRichMedia, ackInteraction) funnel through here, so this blocks every outbound API interaction.
Source
Thrown at platform/qqbot/qqbot.go:316
return "", fmt.Errorf("qqbot: upload rich media: empty file_info")
}
return result.FileInfo, nil
}
// apiRequestJSON is like apiRequest but also decodes the response body into result.
func (p *Platform) apiRequestJSON(method, url string, body any, result any) error {
var bodyReader io.Reader
if body != nil {
data, err := json.Marshal(body)
if err != nil {
return fmt.Errorf("qqbot: marshal body: %w", err)
}
bodyReader = bytes.NewReader(data)
}
token, err := p.getAccessToken()
if err != nil {
return fmt.Errorf("qqbot: get token: %w", err)
}
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 {View on GitHub (pinned to 4000b2338a)
Solutions
- Verify appId and appSecret in the [platform.qqbot] config section against the QQ Open Platform console.
- Test network reachability to the QQ API token endpoint from the host running cc-connect (curl the apiBase).
- Run `cc-connect doctor` to check credentials and connectivity.
- Check that the qqbot app is approved/enabled and the secret was not recently rotated.
- Inspect the wrapped error text — it names the underlying cause (auth refused vs network timeout).
Example fix
// before (config.toml) [platforms.qqbot] appId = "" appSecret = "stale-secret" // after [platforms.qqbot] appId = "123456789" appSecret = "current-secret-from-console"
Defensive patterns
Strategy: validation
Validate before calling
if cfg.QQBot.AppID == "" || cfg.QQBot.AppSecret == "" {
return fmt.Errorf("qqbot: appId/appSecret must be set in config")
}
if err := doctorCheckEndpoint(qqbotTokenURL); err != nil {
return fmt.Errorf("qqbot: token endpoint unreachable: %w", err)
} Try / catch
if err := p.SendFile(ctx, rctx, f); err != nil {
if strings.Contains(err.Error(), "get token") {
// credentials/network problem; do not retry blindly, alert + verify config
slog.Error("qqbot auth unavailable", "err", err)
}
} Prevention
- Validate appId/appSecret at startup, before accepting messages.
- Run `cc-connect doctor` on deploy to catch credential problems early.
- Alert on the first 'get token' failure — every subsequent send will fail too.
- Keep credentials in sync after rotating them in the QQ console.
When it happens
Trigger: Any of uploadRichMedia, ackInteraction, or sendMessage calls apiRequestJSON and getAccessToken returns an error: invalid AppID/AppSecret in config.toml, token endpoint unreachable, or token exchange rejected (e.g. wrong secret, suspended app).
Common situations: Misconfigured qqbot appId/appSecret in config.toml; credentials rotated in the QQ Open Platform console but not updated locally; network egress blocked to the QQ API host; app disabled or sandbox/scope restrictions.
Related errors
- qqbot: failed to get access token: %w
- remote returned non-zero code
- cloud_web: token is required
- dingtalk: get access token for emotion: %w
- dingtalk: get access token: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/f554302b23d5eec6.
Report an issue: GitHub.