larksuite/cli · error
parse response: %w
Error message
parse response: %w
What it means
This error wraps a failure to parse the HTTP response body of the bot-info call as JSON (or decode it into the envelope struct). It only fires when the status code was < 400 — i.e. the server said OK but the body was not the expected {code,msg,data} shape. The %w preserves the json/decode error for diagnosis.
Source
Thrown at internal/identitydiag/diagnostics.go:427
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)
id.GrantedAt = formatMillis(token.GrantedAt)
}
View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Read the wrapped parse error for the exact JSON syntax/shape problem.
- Check for a proxy or TLS-intercepting appliance rewriting responses; bypass it for open.feishu.cn / open.larksuite.com.
- Retry the request — a truncated 2xx body is often transient network damage.
- Confirm the configured Open endpoint actually serves the Lark OpenAPI (no typo'd override).
Defensive patterns
Strategy: retry
Try / catch
info, err := fetchBotInfo(ctx, f, cfg, token)
if err != nil {
if strings.HasPrefix(err.Error(), "parse response:") {
// 2xx but non-JSON: middlebox interference or truncation — retry once, then surface
if retryErr := retry.Once(ctx, func() error { _, err = fetchBotInfo(ctx, f, cfg, token); return err }); retryErr != nil {
return fmt.Errorf("non-JSON response from endpoint, check proxy: %w", retryErr)
}
return nil
}
return err
} Prevention
- Exclude Lark endpoints from TLS-inspecting appliances.
- Avoid flaky networks or enforce keep-alives for diagnostics calls.
- Verify endpoint overrides serve the real Lark OpenAPI.
- Test connectivity with a plain JSON fetch to the endpoint before running full diagnostics.
When it happens
Trigger: fetchBotInfo gets a 2xx response but json.Unmarshal/decode of the body into the envelope fails (parseErr != nil). Reached via diagnoseBot or diagnoseExternalBot.
Common situations: A middlebox (proxy, captive portal, security appliance) intercepting HTTPS and returning HTML; truncated response due to connection reset mid-body; wrong endpoint serving JSON of a different shape; content-encoding mismatch (gzip issues).
Related errors
- app registration failed: HTTP %d – response not JSON
- Device authorization failed: HTTP %d – response not JSON
- response parse error: %w (body: %s)
- failed to parse user info: %w
- failed to parse response: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/71f44e67362a539b.
Report an issue: GitHub.