{"record":{"id":"5e24ba78274bf457","repo":"chenhg5/cc-connect","slug":"s-fetch-tenant-access-token-w","errorCode":null,"errorMessage":"%s: fetch tenant access token: %w","messagePattern":"(.+?): fetch tenant access token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/feishu.go","lineNumber":4109,"sourceCode":"\t\treturn err\n\t}\n\n\tfreshToken, refreshErr := p.fetchFreshTenantAccessToken(ctx)\n\tif refreshErr != nil {\n\t\treturn fmt.Errorf(\"%s: %s failed after token refresh attempt: %w (original error: %v)\", p.tag(), operation, refreshErr, err)\n\t}\n\n\tslog.Warn(p.tag()+\": retrying request with fresh tenant access token\", \"operation\", operation)\n\treturn fn(p.replayAPIClient(), larkcore.WithTenantAccessToken(freshToken))\n}\n\nfunc (p *Platform) fetchFreshTenantAccessToken(ctx context.Context) (string, error) {\n\tresp, err := p.replayAPIClient().GetTenantAccessTokenBySelfBuiltApp(ctx, &larkcore.SelfBuiltTenantAccessTokenReq{\n\t\tAppID:     p.appID,\n\t\tAppSecret: p.appSecret,\n\t})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"%s: fetch tenant access token: %w\", p.tag(), err)\n\t}\n\tif !resp.Success() {\n\t\treturn \"\", fmt.Errorf(\"%s: fetch tenant access token code=%d msg=%s\", p.tag(), resp.Code, resp.Msg)\n\t}\n\tif strings.TrimSpace(resp.TenantAccessToken) == \"\" {\n\t\treturn \"\", fmt.Errorf(\"%s: fetch tenant access token returned empty token\", p.tag())\n\t}\n\treturn resp.TenantAccessToken, nil\n}\n\nfunc (p *Platform) replayAPIClient() *lark.Client {\n\tp.replayClientMu.Lock()\n\tdefer p.replayClientMu.Unlock()\n\tif p.replayClient == nil {\n\t\tp.replayClient = newFeishuReplayClient(p.appID, p.appSecret, p.domain)\n\t}\n\treturn p.replayClient\n}","sourceCodeStart":4091,"sourceCodeEnd":4127,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L4091-L4127","documentation":"Wraps a transport-level failure from the SDK's GetTenantAccessTokenBySelfBuiltApp call used to fetch a fresh tenant_access_token. The token request never completed — network, DNS, TLS, or SDK-level error — so no fresh token is available for the retry.","triggerScenarios":"p.replayAPIClient().GetTenantAccessTokenBySelfBuiltApp returns err != nil during the token-refresh retry path, typically after an API call failed with an invalid-token error.","commonSituations":"Feishu auth endpoint outage, host offline, proxy blocking the auth domain, or a malformed appID/appSecret causing an SDK-level error before the request is sent.","solutions":["Check outbound connectivity to the Feishu auth endpoint from the host.","Verify app_id/app_secret are non-empty and correctly set in config.toml.","Retry — transient auth-endpoint failures usually resolve; ensure the outer transient retry covers this path.","Inspect the wrapped error for TLS/DNS specifics to pinpoint the network layer at fault."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if p.appID == \"\" || p.appSecret == \"\" {\n\treturn errors.New(\"feishu app_id/app_secret not configured\")\n}","typeGuard":null,"tryCatchPattern":"token, err := p.fetchFreshTenantAccessToken(ctx)\nif err != nil {\n\tif isNetworkError(errors.Unwrap(err)) {\n\t\t// retry with backoff; auth endpoint may be temporarily down\n\t}\n\treturn err\n}","preventionTips":["Check config values at startup and fail fast on empty credentials.","Monitor connectivity to the Feishu auth domain separately from the API domain.","Bound token-refresh retries to avoid cascading load.","Log the unwrapped cause for every token fetch failure."],"tags":["feishu","lark","auth","token","network"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}