chenhg5/cc-connect · error

token request failed: %w

Error message

token request failed: %w

What it means

refreshToken posts appId/clientSecret to QQ's OAuth token endpoint; this error wraps a transport-level failure of that POST (platform/qqbot/qqbot.go:576). It means the HTTP request itself never completed — DNS, TCP, TLS, or proxy failure — not an HTTP error status from the server.

Source

Thrown at platform/qqbot/qqbot.go:576

		messageType: "c2c",
		userOpenID:  parts[1],
		sessionKey:  sessionKey,
	}, nil
}

// ---------------------------------------------------------------------------
// OAuth2 Token Management
// ---------------------------------------------------------------------------

func (p *Platform) refreshToken() error {
	body, _ := json.Marshal(map[string]string{
		"appId":        p.appID,
		"clientSecret": p.appSecret,
	})

	resp, err := core.HTTPClient.Post(tokenURL, "application/json", bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("token request failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		raw, _ := io.ReadAll(resp.Body)
		return fmt.Errorf("token request returned %d: %s", resp.StatusCode, raw)
	}

	var result struct {
		AccessToken string `json:"access_token"`
		ExpiresIn   string `json:"expires_in"`
	}
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return fmt.Errorf("token response decode: %w", err)
	}
	if result.AccessToken == "" {
		return fmt.Errorf("empty access_token in response")
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check the wrapped cause (%w) to identify DNS vs TCP vs TLS vs timeout.
  2. Verify outbound HTTPS connectivity from the host to the QQ Bot token endpoint.
  3. Clear/fix HTTP_PROXY/HTTPS_PROXY environment variables if a proxy is misconfigured.
  4. Add retry with backoff around platform start, or ensure the daemon restarts on repeated failures.

Example fix

// before
if err := platform.Start(ctx); err != nil { panic(err) }
// after
if err := platform.Start(ctx); err != nil {
    if strings.Contains(err.Error(), "token request failed") {
        slog.Warn("qqbot token fetch failed, retrying", "err", err)
        time.Sleep(5 * time.Second)
        err = platform.Start(ctx)
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// before starting the platform:
conn, err := net.DialTimeout("tcp", "api.sgroup.qq.com:443", 5*time.Second)
if err != nil { return fmt.Errorf("QQ Bot API unreachable: %w", err) }
conn.Close()

Try / catch

if err := platform.Start(ctx); err != nil {
    if strings.Contains(err.Error(), "token request failed") {
        // network-level failure: retry with backoff
        backoff := 5 * time.Second
        for i := 0; i < 3; i++ {
            time.Sleep(backoff); backoff *= 2
            if err = platform.Start(ctx); err == nil { break }
        }
    }
}

Prevention

When it happens

Trigger: Any code path calling refreshToken (startup via connectGateway, getAccessToken on expiry, 401-retry in apiRequest) when core.HTTPClient.Post returns an error: network down, DNS failure, TLS error, request timeout, proxy misconfiguration.

Common situations: Host without internet access; corporate firewall blocking api.sgroup.qq.com; bad HTTP_PROXY env vars; transient network blips during token refresh after the 2-hour token lifetime.

Related errors


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