{"record":{"id":"7f8b2a648d2420a4","repo":"sipeed/picoclaw","slug":"bot-info-api-error-code-d","errorCode":null,"errorMessage":"bot info api error (code=%d)","messagePattern":"bot info api error \\(code=(.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/channels/feishu/feishu_64.go","lineNumber":730,"sourceCode":"\t\tApiPath:                   \"/open-apis/bot/v3/info\",\n\t\tSupportedAccessTokenTypes: []larkcore.AccessTokenType{larkcore.AccessTokenTypeTenant},\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"bot info request: %w\", err)\n\t}\n\n\tvar result struct {\n\t\tCode int `json:\"code\"`\n\t\tBot  struct {\n\t\t\tOpenID string `json:\"open_id\"`\n\t\t} `json:\"bot\"`\n\t}\n\tif err := json.Unmarshal(resp.RawBody, &result); err != nil {\n\t\treturn fmt.Errorf(\"bot info parse: %w\", err)\n\t}\n\tif result.Code != 0 {\n\t\tc.invalidateTokenOnAuthError(result.Code)\n\t\treturn fmt.Errorf(\"bot info api error (code=%d)\", result.Code)\n\t}\n\tif result.Bot.OpenID == \"\" {\n\t\treturn fmt.Errorf(\"bot info: empty open_id\")\n\t}\n\n\tc.botOpenID.Store(result.Bot.OpenID)\n\tlogger.InfoCF(\"feishu\", \"Fetched bot open_id from API\", map[string]any{\n\t\t\"open_id\": result.Bot.OpenID,\n\t})\n\treturn nil\n}\n\n// isBotMentioned checks if the bot was @mentioned in the message.\nfunc (c *FeishuChannel) isBotMentioned(message *larkim.EventMessage) bool {\n\tif message.Mentions == nil {\n\t\treturn false\n\t}\n","sourceCodeStart":712,"sourceCodeEnd":748,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/feishu/feishu_64.go#L712-L748","documentation":"The bot-info endpoint answered with JSON but code != 0: Feishu rejected the call at the business level. Most common is 99991663/99991661 (invalid or expired tenant_access_token), i.e. the app_id/app_secret pair is wrong or the token cache is stale; invalidateTokenOnAuthError(result.Code) already ran so the SDK will re-auth on the next call. Start() logs and continues, degraded.","triggerScenarios":"fetchBotOpenID with bad app credentials (wrong secret, deleted app, wrong app_id), or a stale tenant token after credential rotation.","commonSituations":"Secret rotated in Feishu console but not in deployment config; sandbox vs production credentials mixed up; app disabled by admin.","solutions":["Map the code: 99991661/99991663 means verify app_id/app_secret in the Feishu console and redeploy","If credentials are correct, the token invalidation already scheduled a refresh - retry the operation","Other codes: check the Feishu API docs for /bot/v3/info specifics","Alert on this at startup when mention detection is a required feature"],"exampleFix":"// before: only logged, easy to miss\n// logger.ErrorCF(\"feishu\", \"Failed to fetch bot open_id ...\")\n\n// after: make credential-class failures loud\nif err := c.fetchBotOpenID(ctx); err != nil {\n\tif strings.Contains(err.Error(), \"bot info api error\") {\n\t\tlogger.Error(\"feishu credentials likely invalid\", \"err\", err)\n\t}\n}","handlingStrategy":"try-catch","validationCode":"null","typeGuard":"func isBotInfoAuthFailure(err error) bool {\n\tif err == nil { return false }\n\tm := regexp.MustCompile(`bot info api error \\(code=(\\d+)\\)`).FindStringSubmatch(err.Error())\n\tif m == nil { return false }\n\tcode, _ := strconv.Atoi(m[1])\n\treturn code == 99991661 || code == 99991663\n}","tryCatchPattern":"err := fetchBotInfo(ctx)\nif isBotInfoAuthFailure(err) {\n\t// invalidateTokenOnAuthError already cleared the cached token:\n\t// one retry lets the SDK mint a fresh tenant_access_token\n\ttime.Sleep(time.Second)\n\terr = fetchBotInfo(ctx)\n}\nif err != nil {\n\tlogger.Warn(\"bot open_id unavailable; @mention detection degraded\", \"err\", err)\n}","preventionTips":["Verify app_id/app_secret immediately after any credential rotation","Keep sandbox and production credential sets clearly separated","Alert on auth-class bot-info failures at startup - everything else will fail too","One retry after token invalidation; repeated auth failure means wrong credentials"],"tags":["feishu","auth","credentials","bot-info","api-error"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}