{"record":{"id":"98ef6ae64e5a7d97","repo":"chenhg5/cc-connect","slug":"api-code-d","errorCode":null,"errorMessage":"api code=%d","messagePattern":"api code=(.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/feishu.go","lineNumber":3827,"sourceCode":"\n// fetchBotOpenID retrieves the bot's open_id via the Feishu bot info API.\nfunc (p *Platform) fetchBotOpenID() (string, error) {\n\tresp, err := p.client.Get(context.Background(),\n\t\t\"/open-apis/bot/v3/info\", nil, larkcore.AccessTokenTypeTenant)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"api call: %w\", err)\n\t}\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(\"parse response: %w\", err)\n\t}\n\tif result.Code != 0 {\n\t\treturn \"\", fmt.Errorf(\"api code=%d\", result.Code)\n\t}\n\treturn result.Bot.OpenID, nil\n}\n\nfunc isBotMentioned(mentions []*larkim.MentionEvent, botOpenID string) bool {\n\tfor _, m := range mentions {\n\t\tif m.Id != nil && m.Id.OpenId != nil && *m.Id.OpenId == botOpenID {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// filterQuotedFilesForUser applies the two gating rules for issue #1560\n// without downloading anything yet:\n//  1. The triggering message must explicitly @-mention the bot. We never\n//     pull quoted files for messages that quote a file but do not address\n//     the bot — avoids silent background work on every chatter message","sourceCodeStart":3809,"sourceCodeEnd":3845,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L3809-L3845","documentation":"Thrown when the Feishu bot-info API responds successfully at the HTTP layer but the envelope-level business code is non-zero, meaning Feishu rejected the operation (auth, permission, or app issue). The numeric Feishu code is embedded in the message for diagnosis.","triggerScenarios":"Calling the bot-info endpoint with an app whose tenant_access_token is invalid/expired, the app lacks bot capability enabled, or lacks permission to read bot info — Feishu returns code!=0 in the body.","commonSituations":"App not configured as a bot in the Feishu developer console, missing bot:info scope, wrong app_id/app_secret in config.toml, or app not published to the tenant.","solutions":["Look up the numeric code in Feishu's API error-code docs to identify the exact cause.","Verify app_id/app_secret in config.toml and that the token fetch succeeds.","Enable bot capability and the required scopes in the Feishu developer console, then republish the app.","Re-fetch a fresh tenant_access_token if the code indicates token invalidity (e.g. 99991661/99991663)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-flight: verify credentials by fetching token before calling bot-info\n_, err := fetchFreshTenantAccessToken(ctx)\nif err != nil { /* abort early */ }","typeGuard":"func botInfoOK(result botInfoResult) bool { return result.Code == 0 && result.Bot.OpenID != \"\" }","tryCatchPattern":"botID, err := getBotOpenID(ctx)\nif err != nil {\n\tif strings.Contains(err.Error(), \"code=99991\") { /* token problem: refresh */ }\n\treturn err\n}","preventionTips":["Enable bot capability and required scopes before deploying.","Validate app_id/app_secret at startup with a health check.","Republish the app after any scope change.","Map Feishu error codes to actionable messages in monitoring."],"tags":["feishu","lark","api","error-code"],"backgroundTag":"api-error-response","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"}