{"record":{"id":"2efd3af5d8136c09","repo":"larksuite/cli","slug":"user-info-api-error-d-s","errorCode":null,"errorMessage":"user_info API error: [%d] %s","messagePattern":"user_info API error: \\[(.+?)\\] (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/credential/user_info.go","lineNumber":53,"sourceCode":"\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"user_info API returned HTTP %d\", resp.StatusCode)\n\t}\n\n\tvar result struct {\n\t\tCode int    `json:\"code\"`\n\t\tMsg  string `json:\"msg\"`\n\t\tData struct {\n\t\t\tOpenID string `json:\"open_id\"`\n\t\t\tName   string `json:\"name\"`\n\t\t} `json:\"data\"`\n\t}\n\tif err := json.NewDecoder(resp.Body).Decode(&result); err != nil {\n\t\treturn nil, err\n\t}\n\tif result.Code != 0 {\n\t\treturn nil, fmt.Errorf(\"user_info API error: [%d] %s\", result.Code, result.Msg)\n\t}\n\treturn &userInfo{OpenID: result.Data.OpenID, Name: result.Data.Name}, nil\n}\n","sourceCodeStart":35,"sourceCodeEnd":57,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/credential/user_info.go#L35-L57","documentation":"The user_info endpoint returned HTTP 200 but the JSON envelope carried a non-zero code — an API-level business error. The message includes the legacy Lark code and msg fields, so the exact failure reason is in the error text.","triggerScenarios":"result.Code != 0 after decoding a 200 response from authen/v1/user_info: invalid access token (code 99991663/99991661 family), insufficient app scopes/permissions, token belonging to a different app, or user not accessible to the app.","commonSituations":"Calling user_info with an app_access_token instead of a user_access_token; missing contact/user-info scopes on the app; expired user token that still passes an auth gateway but fails business validation; app installed in a tenant lacking the required permissions.","solutions":["Read the [%d] code in the message and look it up in the Lark error-code docs; auth/token codes (9999166x) mean re-obtain the user_access_token.","Verify the app has the required scopes (e.g. contact:user.base:readonly / user info scope) and the user has re-consented after scope changes.","Confirm you pass a user_access_token (not app/tenant token) in the Authorization header.","If permission codes persist, republish the app version with the new scopes and re-install/authorize in the tenant."],"exampleFix":"// before\ntok := appTenantToken() // wrong token type\ninfo, err := enrichUserInfo(ctx, tok)\n\n// after\ntok := userAccessTokenFromOAuth(ctx) // user_access_token\ninfo, err := enrichUserInfo(ctx, tok)\nif err != nil && strings.Contains(err.Error(), \"9999166\") {\n    tok = userAccessTokenFromOAuth(ctx) // token expired/invalid: re-run OAuth\n    info, err = enrichUserInfo(ctx, tok)\n}","handlingStrategy":"validation","validationCode":"func validateUserAccessPrereqs(tok string) error {\n    if tok == \"\" { return errors.New(\"user_access_token required for user_info\") }\n    if strings.HasPrefix(tok, \"t-\") { return errors.New(\"looks like a tenant/app token; user_info needs a user_access_token\") }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"info, err := enrichUserInfo(ctx, userToken)\nif err != nil {\n    var code int\n    if _, scan := fmt.Sscanf(err.Error(), \"user_info API error: [%d]\", &code); scan == nil {\n        switch code {\n        case 99991663, 99991661, 99991668: // token invalid/expired family\n            userToken = refreshUserAccessToken(ctx)\n            info, err = enrichUserInfo(ctx, userToken)\n        default: // permission/scope issue: do not retry, fix app config\n            return fmt.Errorf(\"user_info rejected (code %d): grant scopes and re-auth\", code)\n        }\n    }\n    if err != nil { return err }\n}","preventionTips":["Always use a user_access_token, never an app/tenant token, for authen/v1/user_info.","Declare and publish all required user-info scopes before first authorization, so consent covers them.","Re-run the OAuth consent flow after any scope change to the app.","Map known Lark error codes (9999166x auth family) to token-refresh handling in your integration."],"tags":["api-error","user-info","permissions","error-code"],"backgroundTag":"lark-api-error-code","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"}