chenhg5/cc-connect · error
%s: %s failed after token refresh attempt: %w (original erro
Error message
%s: %s failed after token refresh attempt: %w (original error: %v)
What it means
Raised by withFreshTenantAccessTokenRetry: the original API call failed with an invalid-tenant-access-token error, a fresh token fetch was attempted, but fetching the new token itself failed. The error chains both the refresh failure (%w) and the original API error for diagnosis.
Source
Thrown at platform/feishu/feishu.go:4096
return fmt.Errorf("%s: %s api call: %w", p.tag(), op, err)
}
if !resp.Success() {
return fmt.Errorf("%s: %s failed code=%d msg=%s", p.tag(), op, resp.Code, resp.Msg)
}
return nil
})
})
}
func (p *Platform) withFreshTenantAccessTokenRetry(ctx context.Context, operation string, fn feishuRequestFunc) error {
err := fn(p.client)
if !isTenantAccessTokenInvalid(err) {
return err
}
freshToken, refreshErr := p.fetchFreshTenantAccessToken(ctx)
if refreshErr != nil {
return fmt.Errorf("%s: %s failed after token refresh attempt: %w (original error: %v)", p.tag(), operation, refreshErr, err)
}
slog.Warn(p.tag()+": retrying request with fresh tenant access token", "operation", operation)
return fn(p.replayAPIClient(), larkcore.WithTenantAccessToken(freshToken))
}
func (p *Platform) fetchFreshTenantAccessToken(ctx context.Context) (string, error) {
resp, err := p.replayAPIClient().GetTenantAccessTokenBySelfBuiltApp(ctx, &larkcore.SelfBuiltTenantAccessTokenReq{
AppID: p.appID,
AppSecret: p.appSecret,
})
if err != nil {
return "", fmt.Errorf("%s: fetch tenant access token: %w", p.tag(), err)
}
if !resp.Success() {
return "", fmt.Errorf("%s: fetch tenant access token code=%d msg=%s", p.tag(), resp.Code, resp.Msg)
}
if strings.TrimSpace(resp.TenantAccessToken) == "" {View on GitHub (pinned to 4000b2338a)
Solutions
- Inspect the wrapped refreshErr: if it's a network error, check connectivity to the Feishu token endpoint.
- Verify app_id/app_secret are still valid and unchanged in config.toml.
- Check the app is enabled and not deactivated in the Feishu developer console.
- Restart the service after fixing credentials so cached state is rebuilt.
Example fix
// before
return fmt.Errorf("%s: %s failed after token refresh attempt: %w (original error: %v)", p.tag(), operation, refreshErr, err)
// after
slog.Error(p.tag()+": token refresh failed", "operation", operation, "refreshErr", refreshErr, "originalErr", err)
return fmt.Errorf("%s: %s failed after token refresh attempt: %w (original error: %v)", p.tag(), operation, refreshErr, err) Defensive patterns
Strategy: retry
Validate before calling
// startup credential check
if _, err := fetchFreshTenantAccessToken(ctx); err != nil {
return fmt.Errorf("invalid feishu credentials: %w", err)
} Try / catch
err := doFeishuCall(ctx)
if err != nil && strings.Contains(err.Error(), "token refresh attempt") {
// credentials invalid or auth endpoint down: alert operator, do not hot-retry
notifyOps(err)
} Prevention
- Validate credentials at startup, not just at first API failure.
- Alert on token-refresh failures — they mean auth is broken, not transient.
- Track app secret rotations in the Feishu console.
- Keep a bounded refresh retry to avoid hammering the auth endpoint.
When it happens
Trigger: An Im.Message reply/create call fails with isTenantAccessTokenInvalid(err)==true, and the subsequent p.fetchFreshTenantAccessToken(ctx) returns an error (network failure or API rejection while obtaining the token).
Common situations: App secret revoked or rotated in the Feishu console while the service runs, Feishu auth endpoint unreachable, or app disabled — token refresh is impossible so the original token-expiry error persists.
Related errors
- %s: fetch tenant access token: %w
- %s: fetch tenant access token code=%d msg=%s
- parse response: %w
- api code=%d
- %s: chatID is empty, cannot send new message
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/5e840d438186ff9c.
Report an issue: GitHub.