chenhg5/cc-connect · error

empty access_token in response

Error message

empty access_token in response

What it means

The token response parsed as valid JSON but the access_token field was empty or missing. refreshToken rejects this explicitly (platform/qqbot/qqbot.go:593) because an empty token cannot authenticate subsequent API calls. This typically means QQ accepted the request but refused to issue a token, often returning an error payload with different field names.

Source

Thrown at platform/qqbot/qqbot.go:593

	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")
	}

	var expiresSec int
	_, _ = fmt.Sscanf(result.ExpiresIn, "%d", &expiresSec)
	if expiresSec <= 0 {
		expiresSec = 7200
	}

	p.tokenMu.Lock()
	p.token = result.AccessToken
	p.tokenExpiry = time.Now().Add(time.Duration(expiresSec) * time.Second)
	p.tokenMu.Unlock()

	slog.Debug("qqbot: access token refreshed", "expires_in", expiresSec)
	return nil
}

// getAccessToken returns the current token, refreshing if expired or near-expiry.

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Log the full response body to see the actual fields QQ returned (e.g. an error code/message object).
  2. Verify in the QQ open platform that the bot app has the required scopes and is approved for group/c2c messaging.
  3. Re-check appId/clientSecret — some QQ errors surface as 200 + error body rather than 4xx.
  4. If the key name changed, update cc-connect to a version matching the current QQ Bot API, or patch the result struct's json tag.
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight credential check via curl before deploying:
// curl -s -X POST <tokenURL> -d '{"appId":"...","clientSecret":"..."}' | jq -e '.access_token != ""'

Try / catch

if err := platform.Start(ctx); err != nil {
    if strings.Contains(err.Error(), "empty access_token") {
        slog.Error("QQ refused token issuance (check app scopes/publish status); raw response logged at debug")
    }
}

Prevention

When it happens

Trigger: refreshToken decodes a 200 JSON body whose access_token field is "" — e.g. QQ returned an error object (code/message) with HTTP 200, or the appId is valid but the app lacks permission for this endpoint.

Common situations: App credentials valid but bot not yet published/scoped for the group/c2c APIs; QQ returning an application-level error inside a 200 response; response schema drift where the token lives under a different JSON key.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


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