chenhg5/cc-connect · error

get access token: %w

Error message

get access token: %w

What it means

createAICard first acquires a DingTalk access token via p.getAccessToken(); any failure is wrapped as 'get access token: %w' and aborts creation of the streaming AI card. This is an authentication/credentials failure against the DingTalk Open API — the appKey/appSecret exchange or token fetch failed, so no card can be created.

Source

Thrown at platform/dingtalk/card.go:63

	_, _ = rand.Read(b)
	return fmt.Sprintf("card_%d_%s", time.Now().UnixMilli(), hex.EncodeToString(b))
}

// generateGUID generates a UUID-like string for API requests.
func generateGUID() string {
	b := make([]byte, 16)
	_, _ = rand.Read(b)
	// Set version (4) and variant bits
	b[6] = (b[6] & 0x0f) | 0x40
	b[8] = (b[8] & 0x3f) | 0x80
	return fmt.Sprintf("%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:16])
}

// createAICard creates a new AI Card instance and delivers it to the conversation.
func (p *Platform) createAICard(ctx context.Context, rc replyContext) (*aiCard, error) {
	token, err := p.getAccessToken()
	if err != nil {
		return nil, fmt.Errorf("get access token: %w", err)
	}

	outTrackId := generateOutTrackID()
	isGroup := rc.isGroup

	// Build openSpaceId based on conversation type
	// See: https://open.dingtalk.com/document/development/create-and-deliver-cards
	var openSpaceId string
	if isGroup {
		openSpaceId = fmt.Sprintf("dtv1.card//IM_GROUP.%s", rc.conversationId)
	} else {
		openSpaceId = fmt.Sprintf("dtv1.card//IM_ROBOT.%s", rc.senderStaffId)
	}

	// Build card data
	cardParamMap := map[string]string{
		"config":          `{"autoLayout":true,"enableForward":true}`,
		p.cardTemplateKey: "",

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the wrapped error: if it's an HTTP/auth error, re-check appKey and appSecret in the dingtalk config and regenerate the secret if rotated
  2. Test outbound connectivity to DingTalk's token endpoint from the host (curl the API)
  3. Verify the DingTalk app is enabled and has the AI-card/robot permissions granted in the developer console
  4. Add retry with backoff for transient network/rate-limit failures in getAccessToken
  5. Check host clock sync (NTP) if token caching/expiry logic is involved

Example fix

// before (config with rotated secret)
[platforms.dingtalk]
appKey = "dingxxxx"
appSecret = "old-secret"
// after
[platforms.dingtalk]
appKey = "dingxxxx"
appSecret = "newly-generated-secret"
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-flight: verify credentials are present and fetch a token once at startup
if cfg.AppKey == "" || cfg.AppSecret == "" {
    return fmt.Errorf("dingtalk: appKey/appSecret required")
}
if _, err := getAccessToken(); err != nil {
    return fmt.Errorf("dingtalk: credential pre-flight failed: %w", err)
}

Try / catch

// Retry transient failures; abort on auth errors
if _, err := p.getAccessToken(); err != nil {
    if isAuthError(err) {
        slog.Error("dingtalk: bad credentials; fix appKey/appSecret", "err", err)
        return err
    }
    return retryWithBackoff(ctx, p.getAccessToken, 3)
}

Prevention

When it happens

Trigger: p.getAccessToken() returns an error: invalid or expired appKey/appSecret, DingTalk API returning an error (network failure, rate limit, non-2xx), missing credentials in config, or wrong endpoint.

Common situations: Wrong or rotated appSecret in config.toml for the dingtalk platform; DingTalk app disabled or permissions revoked; outbound network blocked to api.dingtalk.com (proxy/firewall); hitting DingTalk API rate limits; system clock skew invalidating cached token logic.

Related errors


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