larksuite/cli · error
connection check: decode: %w (body=%s)
Error message
connection check: decode: %w (body=%s)
What it means
After the connection-check API responds, CheckRemoteConnections decodes the body into a struct with code/msg/data.online_instance_cnt. If json.Unmarshal fails, the error is wrapped as 'connection check: decode: %w (body=%s)' and the (length-bounded, control-character-defanged) raw body is embedded for diagnosis. This means the endpoint was reachable but the payload was not the expected JSON shape.
Source
Thrown at internal/event/consume/remote_preflight.go:30
)
type APIClient = event.APIClient
// CheckRemoteConnections returns the count of active WebSocket connections for this app.
func CheckRemoteConnections(ctx context.Context, client APIClient) (int, error) {
raw, err := client.CallAPI(ctx, "GET", "/open-apis/event/v1/connection", nil)
if err != nil {
return 0, fmt.Errorf("connection check: %w", err)
}
var result struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
OnlineInstanceCnt int `json:"online_instance_cnt"`
} `json:"data"`
}
if err := json.Unmarshal(raw, &result); err != nil {
return 0, fmt.Errorf("connection check: decode: %w (body=%s)", err, truncateForError(raw))
}
// Distinguish "verified zero" from "check failed" — non-zero code decodes Cnt=0.
if result.Code != 0 {
return 0, fmt.Errorf("connection check: api error code=%d msg=%q", result.Code, result.Msg)
}
return result.Data.OnlineInstanceCnt, nil
}
// truncateForError bounds length and collapses control chars to defang log injection.
func truncateForError(b []byte) string {
const max = 256
s := event.TruncateDiagnostic(string(b), max, "…(truncated)")
out := make([]byte, 0, len(s))
for _, r := range s {
if r == '\n' || r == '\r' || r == '\t' {
out = append(out, ' ')
continue
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Read the embedded body= snippet in the error to see what was actually returned (HTML? empty? partial JSON?).
- Verify the base URL points at the official open domain and that no proxy is rewriting responses.
- Retry the request; if the body is consistently truncated, check for intermediary proxies or MTU/timeout issues.
- Confirm the API contract still matches {code,msg,data.online_instance_cnt} and update the struct if the service schema changed.
Defensive patterns
Strategy: validation
Validate before calling
// Validate the raw response looks like the expected JSON envelope before decoding
var peek struct {
Code *int `json:"code"`
}
if err := json.Unmarshal(raw, &peek); err != nil || peek.Code == nil {
// not the expected schema: log truncateForError(raw) and abort/retry
} Try / catch
_, err := consume.CheckRemoteConnections(ctx, client)
if err != nil {
var decErr *json.UnmarshalError
if errors.As(err, &decErr) || strings.Contains(err.Error(), "decode:") {
// body was not JSON: dump body snippet, retry or fall back
}
} Prevention
- Confirm the base URL hits the official gateway, not an intercepting proxy.
- Check for corporate WAF/SSO pages that return HTML for API paths.
- Pin the API/service version the client was built against and re-verify after upgrades.
- Log the response body (defanged) on decode failure to speed diagnosis.
When it happens
Trigger: json.Unmarshal of the CallAPI response body fails: HTML error/interstitial pages, empty body, truncation, wrong Content-Type gateway responses, or a proxy returning non-JSON text on GET /open-apis/event/v1/connection.
Common situations: Gateway/WAF returning an HTML 502 page, captive portal or proxy intercepting the request, API version change altering the response schema, response body cut off mid-JSON.
Related errors
- failed to parse response: %w
- decode application response: %w
- decode app_versions response: %w
- app registration failed: HTTP %d – response not JSON
- Device authorization failed: HTTP %d – response not JSON
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/0eb3745ae48ad437.
Report an issue: GitHub.