{"record":{"id":"f3197b5fe8edf847","repo":"larksuite/cli","slug":"http-d","errorCode":null,"errorMessage":"HTTP %d","messagePattern":"HTTP %d","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/identitydiag/diagnostics.go","lineNumber":424,"sourceCode":"\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\tparseErr := json.Unmarshal(body, &envelope)\n\n\tif resp.StatusCode >= 400 {\n\t\t// Lark error responses are usually `{code, msg}` envelopes even on\n\t\t// non-2xx — surface them when present so callers see why bot auth\n\t\t// was rejected, not just the bare HTTP code.\n\t\tif parseErr == nil && envelope.Code != 0 {\n\t\t\treturn nil, fmt.Errorf(\"HTTP %d: [%d] %s\", resp.StatusCode, envelope.Code, envelope.Msg)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"HTTP %d\", resp.StatusCode)\n\t}\n\tif parseErr != nil {\n\t\treturn nil, fmt.Errorf(\"parse response: %w\", parseErr)\n\t}\n\tif envelope.Code != 0 {\n\t\treturn nil, fmt.Errorf(\"[%d] %s\", envelope.Code, envelope.Msg)\n\t}\n\tif envelope.Data.OpenID == \"\" {\n\t\treturn nil, errors.New(\"open_id is empty\")\n\t}\n\treturn &botInfo{OpenID: envelope.Data.OpenID, AppName: envelope.Data.AppName}, nil\n}\n\nfunc fillTokenFields(id *Identity, token *larkauth.StoredUAToken) {\n\tid.TokenStatus = larkauth.TokenStatus(token)\n\tid.Scope = token.Scope\n\tid.ExpiresAt = formatMillis(token.ExpiresAt)\n\tid.RefreshExpiresAt = formatMillis(token.RefreshExpiresAt)","sourceCodeStart":406,"sourceCodeEnd":442,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/identitydiag/diagnostics.go#L406-L442","documentation":"This error means the bot-info endpoint returned HTTP >= 400 but the body either did not parse as a Lark {code,msg} envelope or the envelope carried code 0, so no Lark business code is available. The CLI falls back to reporting only the HTTP status so callers at least know the request failed at the transport/HTTP layer.","triggerScenarios":"fetchBotInfo receives a 4xx/5xx response whose body fails envelope parsing (parseErr != nil) or whose envelope.Code == 0 — e.g. an HTML gateway error page or empty body. Reached via diagnoseBot/diagnoseExternalBot.","commonSituations":"Corporate proxy or gateway returning an HTML 502/503 error page; wrong endpoint URL hitting a non-Lark service; auth sidecar returning a non-JSON body; transient infrastructure errors at the Lark edge.","solutions":["Check the HTTP status in the message: 401/403 point to token problems — refresh credentials; 5xx point to server/gateway issues — retry later.","Verify the resolved Open endpoint URL is correct for the configured brand (no proxy or custom override rewriting it).","Inspect proxy/gateway logs if a corporate proxy sits between the CLI and Lark.","Retry the diagnostics run; if persistent, capture the raw response (verbose/debug logging) and compare against the expected envelope."],"exampleFix":"// before: overridden endpoint points at the wrong host\nconfig: open_api_base_url = \"https://internal-gw.example.com\"\n\n// after\n# remove the override or set the correct Lark open API base\nopen_api_base_url = \"https://open.feishu.cn\"","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"info, err := fetchBotInfo(ctx, f, cfg, token)\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"HTTP \") && !strings.Contains(err.Error(), \"[\") {\n        // no Lark code available: likely gateway/infra — retry with backoff\n        return retry.WithBackoff(ctx, 3, func() error { return fetchBotInfo(ctx, f, cfg, token) })\n    }\n    return err\n}","preventionTips":["Do not override the Open API base URL unless absolutely necessary.","Bypass TLS-intercepting proxies for open.feishu.cn / open.larksuite.com.","Retry 5xx responses with exponential backoff.","Capture raw responses (debug mode) when the error recurs to identify the rewriting middlebox."],"tags":["http","api-error","network","gateway"],"backgroundTag":"http-5xx-server-error","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"}