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

  1. Read the wrapped parse error for the exact JSON syntax/shape problem.
  2. Check for a proxy or TLS-intercepting appliance rewriting responses; bypass it for open.feishu.cn / open.larksuite.com.
  3. Retry the request — a truncated 2xx body is often transient network damage.
  4. 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

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


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/71f44e67362a539b. Report an issue: GitHub.