{"record":{"id":"7df88722df9b5815","repo":"sipeed/picoclaw","slug":"bot-info-request-w","errorCode":null,"errorMessage":"bot info request: %w","messagePattern":"bot info request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/channels/feishu/feishu_64.go","lineNumber":716,"sourceCode":"\t\tinboundCtx.SpaceType = \"tenant\"\n\t\tinboundCtx.SpaceID = *sender.TenantKey\n\t}\n\n\tc.HandleInboundContext(ctx, chatID, content, mediaRefs, inboundCtx, senderInfo)\n\treturn nil\n}\n\n// --- Internal helpers ---\n\n// fetchBotOpenID calls the Feishu bot info API to retrieve and store the bot's open_id.\nfunc (c *FeishuChannel) fetchBotOpenID(ctx context.Context) error {\n\tresp, err := c.client.Do(ctx, &larkcore.ApiReq{\n\t\tHttpMethod:                http.MethodGet,\n\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}","sourceCodeStart":698,"sourceCodeEnd":734,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/feishu/feishu_64.go#L698-L734","documentation":"FeishuChannel.fetchBotOpenID performs a raw larkcore request to GET /open-apis/bot/v3/info and the SDK failed at the transport level before a response parsed. Start() only logs this as a warning and continues: the bot keeps running, but @mention detection may not work because botOpenID stays unset.","triggerScenarios":"The channel's first API call at startup hits a network failure: DNS not ready (common in containers at boot), proxy down, connection refused to open.feishu.cn.","commonSituations":"Container startup racing DNS/network readiness; egress firewall allowing webhooks but blocking the info endpoint; flaky first-hop connectivity.","solutions":["Retry the start or trigger a later open_id refresh - the failure is startup-degrading, not fatal","Ensure egress to open.feishu.cn is available at container boot (init containers or readiness hooks)","If mention detection matters, monitor for the 'Failed to fetch bot open_id' log and alert","Consider memoizing and refreshing the open_id lazily on first mention check"],"exampleFix":"// before\nif err := c.fetchBotOpenID(ctx); err != nil { /* logged, botOpenID empty */ }\n\n// after\nvar err error\nfor i := 0; i < 3 && err != nil; i++ {\n\ttime.Sleep(time.Duration(i) * time.Second) // wait for network readiness\n\terr = c.fetchBotOpenID(ctx)\n}\nif err != nil {\n\tlogger.Warn(\"bot open_id unavailable; @mention detection degraded\")\n}","handlingStrategy":"retry","validationCode":"// wait for network readiness before starting the channel\nfunc waitForEgress(host string, timeout time.Duration) bool {\n\tdeadline := time.Now().Add(timeout)\n\tfor time.Now().Before(deadline) {\n\t\tif _, err := net.DialTimeout(\"tcp\", host+\":443\", time.Second); err == nil {\n\t\t\treturn true\n\t\t}\n\t\ttime.Sleep(500 * time.Millisecond)\n\t}\n\treturn false\n}","typeGuard":"null","tryCatchPattern":"// Start already degrades gracefully; retry only to preserve mention detection\nerr := ch.Start(ctx)\nif err == nil && !ch.HasBotOpenID() {\n\tlogger.Warn(\"bot open_id missing; will retry fetch\", \"err\", lastFetchErr)\n\tgo func() { _ = ch.RefreshBotOpenID(ctx) }() // or restart the channel later\n}","preventionTips":["Order container startup so DNS/network precede channel Start (readiness gates)","Monitor the 'Failed to fetch bot open_id' log when @mention features matter","Refresh open_id lazily: first mention check can trigger a fetch instead of failing silently","Remember the error is non-fatal by design - the bot still receives messages"],"tags":["feishu","network","startup","bot-info","degraded"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}