{"record":{"id":"66dbcd3da9acc20f","repo":"larksuite/cli","slug":"d-s-66dbcd","errorCode":null,"errorMessage":"[%d] %s","messagePattern":"\\[%d\\] %s","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/identitydiag/diagnostics.go","lineNumber":430,"sourceCode":"\t\t\tAppName string `json:\"app_name\"`\n\t\t} `json:\"bot\"`\n\t}\n\tparseErr := json.Unmarshal(body, &envelope)\n\n\tif resp.StatusCode >= 400 {\n\t\t// Lark error responses are usually `{code, msg}` envelopes even on\n\t\t// non-2xx — surface them when present so callers see why bot auth\n\t\t// was rejected, not just the bare HTTP code.\n\t\tif parseErr == nil && envelope.Code != 0 {\n\t\t\treturn nil, fmt.Errorf(\"HTTP %d: [%d] %s\", resp.StatusCode, envelope.Code, envelope.Msg)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"HTTP %d\", resp.StatusCode)\n\t}\n\tif parseErr != nil {\n\t\treturn nil, fmt.Errorf(\"parse response: %w\", parseErr)\n\t}\n\tif envelope.Code != 0 {\n\t\treturn nil, fmt.Errorf(\"[%d] %s\", envelope.Code, envelope.Msg)\n\t}\n\tif envelope.Data.OpenID == \"\" {\n\t\treturn nil, errors.New(\"open_id is empty\")\n\t}\n\treturn &botInfo{OpenID: envelope.Data.OpenID, AppName: envelope.Data.AppName}, nil\n}\n\nfunc fillTokenFields(id *Identity, token *larkauth.StoredUAToken) {\n\tid.TokenStatus = larkauth.TokenStatus(token)\n\tid.Scope = token.Scope\n\tid.ExpiresAt = formatMillis(token.ExpiresAt)\n\tid.RefreshExpiresAt = formatMillis(token.RefreshExpiresAt)\n\tid.GrantedAt = formatMillis(token.GrantedAt)\n}\n\nfunc formatMillis(ms int64) string {\n\tif ms <= 0 {\n\t\treturn \"\"","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/identitydiag/diagnostics.go#L412-L448","documentation":"This error means the bot-info endpoint returned HTTP 2xx and the body parsed, but the Lark envelope carries a non-zero business code — the API-level failure signal. Unlike the >=400 case, this is a well-formed Lark error response on a success status, e.g. invalid token, permission denied, or app not found, with the authoritative Lark code and message.","triggerScenarios":"fetchBotInfo receives a 2xx response, parses it successfully, and envelope.Code != 0. Reached from diagnoseBot or diagnoseExternalBot during identity diagnostics.","commonSituations":"App access token invalid or expired (code 99991663/99991661/99991668); app lacking required scopes/permissions for bot info; app not available in the tenant; invalid param errors from API-side validation.","solutions":["Look up the Lark error code in the message ([code]) against Lark's error-code documentation to identify the exact auth/permission issue.","For token errors, re-authenticate: run the CLI login/token refresh flow so a fresh app/tenant access token is issued.","Verify the app has the bot capability and required scopes (e.g. contact/app info scopes) granted in the developer console.","Re-run identity diagnostics to confirm the envelope code is 0 and bot info resolves."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if token == nil || token.AccessToken == \"\" {\n    return errors.New(\"no access token available; run auth login first\")\n}","typeGuard":null,"tryCatchPattern":"info, err := fetchBotInfo(ctx, f, cfg, token)\nif err != nil {\n    msg := err.Error()\n    if strings.HasPrefix(msg, \"[\") {\n        switch {\n        case strings.Contains(msg, \"99991663\"), strings.Contains(msg, \"99991661\"):\n            return fmt.Errorf(\"invalid/expired token: %w\", err) // trigger re-auth\n        default:\n            return fmt.Errorf(\"Lark API rejected bot info request: %w\", err)\n        }\n    }\n    return err\n}","preventionTips":["Check the Lark error-code table first — the [code] in the message is authoritative.","Grant the app all required bot scopes before running identity diagnostics.","Keep tokens fresh via the CLI's credential refresh flow.","Confirm app availability in the target tenant, not just existence in the console."],"tags":["lark","api-error","authentication","permissions"],"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"}