larksuite/cli · error
HTTP %d
Error message
HTTP %d
What it means
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.
Source
Thrown at internal/identitydiag/diagnostics.go:424
// payload is under "bot", not "data" as the newer Lark API convention.
var envelope struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
OpenID string `json:"open_id"`
AppName string `json:"app_name"`
} `json:"bot"`
}
parseErr := json.Unmarshal(body, &envelope)
if resp.StatusCode >= 400 {
// Lark error responses are usually `{code, msg}` envelopes even on
// non-2xx — surface them when present so callers see why bot auth
// was rejected, not just the bare HTTP code.
if parseErr == nil && envelope.Code != 0 {
return nil, fmt.Errorf("HTTP %d: [%d] %s", resp.StatusCode, envelope.Code, envelope.Msg)
}
return nil, fmt.Errorf("HTTP %d", resp.StatusCode)
}
if parseErr != nil {
return nil, fmt.Errorf("parse response: %w", parseErr)
}
if envelope.Code != 0 {
return nil, fmt.Errorf("[%d] %s", envelope.Code, envelope.Msg)
}
if envelope.Data.OpenID == "" {
return nil, errors.New("open_id is empty")
}
return &botInfo{OpenID: envelope.Data.OpenID, AppName: envelope.Data.AppName}, nil
}
func fillTokenFields(id *Identity, token *larkauth.StoredUAToken) {
id.TokenStatus = larkauth.TokenStatus(token)
id.Scope = token.Scope
id.ExpiresAt = formatMillis(token.ExpiresAt)
id.RefreshExpiresAt = formatMillis(token.RefreshExpiresAt)View on GitHub (pinned to 7fd6ef3c07)
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.
Example fix
// before: overridden endpoint points at the wrong host config: open_api_base_url = "https://internal-gw.example.com" // after # remove the override or set the correct Lark open API base open_api_base_url = "https://open.feishu.cn"
Defensive patterns
Strategy: retry
Try / catch
info, err := fetchBotInfo(ctx, f, cfg, token)
if err != nil {
if strings.HasPrefix(err.Error(), "HTTP ") && !strings.Contains(err.Error(), "[") {
// no Lark code available: likely gateway/infra — retry with backoff
return retry.WithBackoff(ctx, 3, func() error { return fetchBotInfo(ctx, f, cfg, token) })
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- app registration failed: HTTP %d – response not JSON
- Device authorization failed: read body: %v
- failed to read response body in security transport: %w
- response parse error: %w (body: %s)
- failed to read TAT response: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/f3197b5fe8edf847.
Report an issue: GitHub.