{"record":{"id":"881bf2d47ab5528d","repo":"larksuite/cli","slug":"fetch-bot-info-unmarshal-w","errorCode":null,"errorMessage":"fetch bot info: unmarshal: %w","messagePattern":"fetch bot info: unmarshal: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/runner.go","lineNumber":184,"sourceCode":"\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"fetch bot info: %w\", err)\n\t}\n\tif resp.StatusCode >= 400 {\n\t\treturn nil, fmt.Errorf(\"fetch bot info: HTTP %d\", resp.StatusCode)\n\t}\n\t// /open-apis/bot/v3/info returns `{code, msg, bot: {...}}` — the bot\n\t// payload is under \"bot\", not \"data\" as the newer Lark API convention.\n\tvar envelope struct {\n\t\tCode int    `json:\"code\"`\n\t\tMsg  string `json:\"msg\"`\n\t\tData struct {\n\t\t\tOpenID  string `json:\"open_id\"`\n\t\t\tAppName string `json:\"app_name\"`\n\t\t} `json:\"bot\"`\n\t}\n\tif err := json.Unmarshal(resp.RawBody, &envelope); err != nil {\n\t\treturn nil, fmt.Errorf(\"fetch bot info: unmarshal: %w\", err)\n\t}\n\tif envelope.Code != 0 {\n\t\treturn nil, fmt.Errorf(\"fetch bot info: [%d] %s\", envelope.Code, envelope.Msg)\n\t}\n\tif envelope.Data.OpenID == \"\" {\n\t\treturn nil, fmt.Errorf(\"fetch bot info: open_id is empty\")\n\t}\n\treturn &BotInfo{OpenID: envelope.Data.OpenID, AppName: envelope.Data.AppName}, nil\n}\n\n// Ctx returns the context.Context propagated from cmd.Context().\nfunc (ctx *RuntimeContext) Ctx() context.Context { return ctx.ctx }\n\n// getAPIClient returns the cached APIClient, creating it on first use.\n// Thread-safe via sync.OnceValues (initialized in newRuntimeContext).\n// Falls back to direct construction for test contexts that bypass newRuntimeContext.\nfunc (ctx *RuntimeContext) getAPIClient() (*client.APIClient, error) {\n\tif ctx.offline {","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/runner.go#L166-L202","documentation":"The HTTP response body of /bot/v3/info could not be decoded into the expected {code, msg, bot:{open_id, app_name}} envelope. This means the gateway returned an unexpected payload (HTML error page, different schema, truncated body). Note the bot payload lives under \"bot\", not \"data\", per this API's older convention.","triggerScenarios":"json.Unmarshal(resp.RawBody, &envelope) fails — non-JSON body (proxy/auth HTML interstitial), a schema change in the endpoint response, or a corrupted/truncated response.","commonSituations":"Corporate proxy or captive portal returning HTML; API version/gateway changes altering the payload; hitting a mock or wrong environment returning unexpected JSON.","solutions":["Log/inspect resp.RawBody to see the actual payload and confirm it is the expected JSON envelope","If a proxy/SSO layer intercepts requests, bypass or authenticate it so the real Lark API responds","Update the CLI if the endpoint schema changed; verify against the current /bot/v3/info contract"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Confirm the gateway returns JSON before parsing bot info:\nresp, err := http.Get(baseURL + \"/open-apis/bot/v3/info\")\nif err == nil && !strings.HasPrefix(strings.TrimSpace(http.DetectContentType(resp.Body[:512]), \"application/json\") { /* proxy/HTML interstitial */ }","typeGuard":null,"tryCatchPattern":"info, err := ctx.BotInfo()\nif err != nil && strings.Contains(err.Error(), \"unmarshal:\") {\n\t// unexpected payload: check for proxy/auth HTML, schema change\n\treturn fmt.Errorf(\"bot info endpoint returned non-JSON payload: %w\", err)\n}","preventionTips":["Bypass proxies/captive portals that inject HTML into API responses","Pin the CLI to a gateway environment matching the expected /bot/v3/info schema","Update the CLI when Lark changes the response envelope"],"tags":["go","json","unmarshal","api-schema"],"backgroundTag":"json-unmarshal-failed","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"}