larksuite/cli · error

decode application response: %w

Error message

decode application response: %w

What it means

FetchSubscribedCallbacks in internal/appmeta fetches an application's subscribed callbacks from the Lark open-platform API and unmarshals the raw response into a typed envelope. This error wraps any json.Unmarshal failure decoding that response, preserving the underlying syntax/type error via %w.

Source

Thrown at internal/appmeta/app_callbacks.go:35

// weak-dependency skip. Identity must be bot: the endpoint is app-level.
func FetchSubscribedCallbacks(ctx context.Context, client APIClient, appID string) ([]string, error) {
	path := fmt.Sprintf("/open-apis/application/v6/applications/%s?lang=zh_cn", appID)
	raw, err := client.CallAPI(ctx, "GET", path, nil)
	if err != nil {
		return nil, err
	}

	var envelope struct {
		Data struct {
			App struct {
				CallbackInfo *struct {
					SubscribedCallbacks []string `json:"subscribed_callbacks"`
				} `json:"callback_info"`
			} `json:"app"`
		} `json:"data"`
	}
	if err := json.Unmarshal(raw, &envelope); err != nil {
		return nil, fmt.Errorf("decode application response: %w", err)
	}
	// callback_info also carries callback_type (e.g. "websocket"); it is
	// intentionally not parsed or validated. Feishu open-platform callbacks are
	// delivered over WebSocket only (confirmed), matching the CLI's WebSocket
	// event source, so subscribed_callbacks alone is sufficient for the precheck.
	// Revisit and validate callback_type if non-WebSocket delivery ever appears.
	callbacks := []string{}
	if ci := envelope.Data.App.CallbackInfo; ci != nil {
		callbacks = append(callbacks, ci.SubscribedCallbacks...)
	}
	return callbacks, nil
}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Inspect the wrapped cause (%w) to distinguish invalid JSON from type mismatch
  2. Log/print the raw response body to see what was actually returned
  3. Check whether an auth gateway returned an HTML error page or non-200 body
  4. Upgrade/verify the CLI version matches the current app_versions API schema

Example fix

// before: ignoring the wrapped cause
if err := fetch(); err != nil { return err }
// after: surface the decode cause
var derr *json.UnmarshalTypeError
if errors.As(err, &derr) { log.Printf("field %s: %v", derr.Field, derr) }
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check the response looks like JSON before decoding
if len(raw) > 0 && raw[0] != '{' && raw[0] != '[' {
  return fmt.Errorf("non-JSON response: %.100s", raw)
}

Try / catch

items, err := meta.FetchSubscribedCallbacks(ctx, raw)
if err != nil {
  var jsonErr *json.SyntaxError
  if errors.As(err, &jsonErr) { /* log raw body, retry with backoff */ }
  return err
}

Prevention

When it happens

Trigger: The HTTP response body returned by the application API is not valid JSON, or its structure diverges from the envelope (e.g. data.app is a different shape) so unmarshal into the anonymous struct fails.

Common situations: A proxy or captive portal returning HTML instead of JSON; API version changes altering the payload shape; the fetch helper receiving a truncated body on network interruption.

Related errors


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