{"record":{"id":"03440ae35acec2bf","repo":"chenhg5/cc-connect","slug":"parse-response-w-03440a","errorCode":null,"errorMessage":"parse response: %w","messagePattern":"parse response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/feishu.go","lineNumber":3824,"sourceCode":"\t}\n\treturn -1\n}\n\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:","sourceCodeStart":3806,"sourceCodeEnd":3842,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L3806-L3842","documentation":"Thrown by the Feishu platform adapter when the HTTP response body of a 'get bot info' API call cannot be unmarshalled into the expected struct (code + bot.open_id). It wraps the underlying json.Unmarshal error, so the cause is a malformed or unexpected response payload, not a logic error in the caller.","triggerScenarios":"The call to fetch the bot's own open_id receives a 200 response whose RawBody is not valid JSON, or its shape differs from {code, bot.open_id} (e.g. an HTML error page from a proxy, truncated body, or Feishu API version change).","commonSituations":"Corporate proxies/gateways returning HTML interstitials, intermittent network truncation, wrong API base URL pointing at a non-Feishu endpoint, or Feishu changing the response schema for the bot-info endpoint.","solutions":["Log resp.RawBody alongside the wrapped error to see the actual payload returned.","Verify the app/api base URL (Feishu vs Lark domain) and that no proxy is intercepting the request.","Retry the call — transient network truncation often resolves.","Upgrade the larksuite/oapi-sdk and re-check the response schema if Feishu changed the endpoint format."],"exampleFix":"// before\nif err := json.Unmarshal(resp.RawBody, &result); err != nil {\n\treturn \"\", fmt.Errorf(\"parse response: %w\", err)\n}\n// after\nif err := json.Unmarshal(resp.RawBody, &result); err != nil {\n\treturn \"\", fmt.Errorf(\"parse response: %w (body: %.200s)\", err, string(resp.RawBody))\n}","handlingStrategy":"try-catch","validationCode":"if len(resp.RawBody) == 0 || resp.RawBody[0] != '{' {\n\t// body is not JSON; do not attempt Unmarshal\n}","typeGuard":"func isValidJSONBody(b []byte) bool { return json.Valid(b) }","tryCatchPattern":"botID, err := getBotOpenID(ctx)\nif err != nil {\n\tvar parseErr *json.UnmarshalTypeError\n\tif errors.As(err, &parseErr) { /* schema changed: log body, alert */ }\n\treturn fmt.Errorf(\"bot info unavailable: %w\", err)\n}","preventionTips":["Log resp.RawBody on every unmarshal failure.","Pin and regularly update the lark SDK.","Alert on non-JSON bodies (proxy interception).","Monitor Feishu API changelog for schema changes."],"tags":["feishu","json","unmarshal","lark"],"backgroundTag":"json-unmarshal-failed","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"}