{"record":{"id":"ec266a87041277e8","repo":"larksuite/cli","slug":"failed-to-verify-user-identity-w","errorCode":null,"errorMessage":"failed to verify user identity: %w","messagePattern":"failed to verify user identity: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/credential/credential_provider.go","lineNumber":248,"sourceCode":"\tif err != nil {\n\t\tvar blockErr *extcred.BlockError\n\t\tif errors.As(err, &blockErr) {\n\t\t\treturn nil // provider explicitly blocks UAT; skip enrichment\n\t\t}\n\t\treturn fmt.Errorf(\"failed to resolve UAT for user identity verification: %w\", err)\n\t}\n\tif !found {\n\t\treturn nil\n\t}\n\t// Have UAT — must verify and resolve identity\n\thc, err := p.httpClient()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to get HTTP client for user_info: %w\", err)\n\t}\n\trequestCtx := core.WithCredentialSource(ctx, tok.Source)\n\tinfo, err := fetchUserInfo(requestCtx, hc, acct.Brand, tok.Token)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to verify user identity: %w\", err)\n\t}\n\tacct.UserOpenId = info.OpenID\n\tacct.UserName = info.Name\n\treturn nil\n}\n\nfunc (p *CredentialProvider) selectedCredentialSource(ctx context.Context) (credentialSource, error) {\n\tif p.selectedSource != nil {\n\t\treturn p.selectedSource, nil\n\t}\n\tif p.defaultAcct == nil {\n\t\treturn nil, nil\n\t}\n\tif _, err := p.ResolveAccount(ctx); err != nil {\n\t\treturn nil, err\n\t}\n\tif p.selectedSource == nil {\n\t\treturn nil, fmt.Errorf(\"credential provider resolved an account without selecting a token source\")","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/credential/credential_provider.go#L230-L266","documentation":"A UAT was resolved and the HTTP client built, but the user_info API call used to verify the token and resolve the user's identity failed. Because holding a UAT makes verification mandatory (security requirement), the failure is wrapped and propagated; callers in doResolveAccount treat enrichment failure as non-fatal only in some paths, clearing UserOpenId/UserName for safety. The wrapped cause distinguishes network errors from API rejections (expired/revoked token, insufficient scopes).","triggerScenarios":"fetchUserInfo(requestCtx, hc, acct.Brand, tok.Token) returns an error — the user_info endpoint returned an error (401/403, token expired or revoked, missing scopes) or the request failed at the transport level.","commonSituations":"UAT expired since being cached; user revoked the app; tenant admin removed required user scopes; network/firewall blocking the accounts endpoint; brand endpoint misconfigured.","solutions":["Read the wrapped cause: if it indicates 401/invalid token, re-authenticate (re-run the login/auth flow) to mint a fresh UAT","If it indicates missing scopes, grant the required user scopes to the app in the Lark/Feishu admin console and re-auth","If it is a network error, fix connectivity/proxy to the accounts endpoint and retry","If enrichment is non-fatal for your flow, handle the error by clearing UserOpenId/UserName rather than aborting, as doResolveAccount does in its tolerant path"],"exampleFix":"var infoErr *errs.APIError\nif errors.As(err, &infoErr) && infoErr.Code == 401 {\n    // UAT expired/invalid — trigger re-login instead of retrying\n}","handlingStrategy":"try-catch","validationCode":"// Pre-flight: only proceed with UAT flows when the token is present and fresh\nif tok, found, err := source.TryResolveToken(ctx, credential.TokenSpec{Type: credential.TokenTypeUAT, AppID: appID}); err == nil && found && !tokenExpired(tok.Token) {\n\t// safe to verify identity\n}","typeGuard":"func isAPIError(err error) bool {\n\tvar ae *errs.APIError\n\treturn errors.As(err, &ae)\n}","tryCatchPattern":"if err := enrichUserInfo(ctx, acct, source); err != nil {\n\tvar apiErr *errs.APIError\n\tif errors.As(err, &apiErr) && (apiErr.HTTPStatus == 401 || apiErr.HTTPStatus == 403) {\n\t\t// token expired/revoked or scopes missing — trigger re-login\n\t} else {\n\t\t// transport failure — safe to retry with backoff\n\t}\n}","preventionTips":["Re-authenticate before UAT expiry instead of relying on stale cached tokens","Confirm required user scopes (user_info / contact scopes) are granted to the app","Handle enrichment as non-fatal by clearing UserOpenId/UserName when strict identity is not required"],"tags":["auth","uat","user-info","api"],"backgroundTag":"uat-identity-verification-failed","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}