chenhg5/cc-connect · error
%s: fetch tenant access token code=%d msg=%s
Error message
%s: fetch tenant access token code=%d msg=%s
What it means
The tenant_access_token request completed but Feishu returned a business error (resp.Success()==false); the Feishu error code and message are included. This typically indicates the app credentials were rejected during token issuance.
Source
Thrown at platform/feishu/feishu.go:4112
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) == "" {
return "", fmt.Errorf("%s: fetch tenant access token returned empty token", p.tag())
}
return resp.TenantAccessToken, nil
}
func (p *Platform) replayAPIClient() *lark.Client {
p.replayClientMu.Lock()
defer p.replayClientMu.Unlock()
if p.replayClient == nil {
p.replayClient = newFeishuReplayClient(p.appID, p.appSecret, p.domain)
}
return p.replayClient
}
func newFeishuReplayClient(appID, appSecret, domain string) *lark.Client {
var opts []lark.ClientOptionFuncView on GitHub (pinned to 4000b2338a)
Solutions
- Look up the embedded code in Feishu docs — 10003/10004 mean credentials are wrong.
- Re-copy app_id/app_secret from the Feishu developer console into config.toml and restart.
- Confirm the app type (self-built vs store) matches the token endpoint being used.
- Verify the correct domain (Feishu vs Lark) matches where the app is registered.
Example fix
// before appSecret = "old-secret" // after # config.toml [platforms.feishu] app_id = "cli_xxx" app_secret = "<current secret from developer console>"
Defensive patterns
Strategy: try-catch
Validate before calling
// verify credentials before deploying
token, err := fetchFreshTenantAccessToken(ctx)
if err != nil && strings.Contains(err.Error(), "code=10003") {
return errors.New("invalid app_id")
} Try / catch
token, err := p.fetchFreshTenantAccessToken(ctx)
if err != nil {
var code int
if extractFeishuCode(err, &code) && (code == 10003 || code == 10004) {
return fmt.Errorf("feishu credentials rejected (code=%d): fix config.toml", code)
}
return err
} Prevention
- Copy app_id/app_secret directly from the developer console; never hand-type.
- Fail fast at startup with a credential smoke test.
- Keep the Feishu vs Lark domain consistent with where the app is registered.
- Rotate secrets via config update + restart, alerting on refresh failures during the window.
When it happens
Trigger: GetTenantAccessTokenBySelfBuiltApp returns a response with code != 0 — most commonly code 10003 (invalid app_id) or 10004 (invalid app_secret) — during the token-refresh retry path.
Common situations: Wrong or rotated app_secret in config.toml, app deleted/disabled in the Feishu developer console, using a Lark (open.larksuite.com) app against Feishu endpoints or vice versa, or store-app credentials used with a self-built token endpoint.
Related errors
- %s: %s failed after token refresh attempt: %w (original erro
- %s: fetch tenant access token: %w
- app_id/app_secret are required
- both --app-id and --app-secret are required
- bind mode requires credentials: use --app id:secret or --app
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/936d2e9c3a3ff53f.
Report an issue: GitHub.