chenhg5/cc-connect · error

decode: %w

Error message

decode: %w

What it means

feishuRegistrationCall wraps JSON decoding failures of the Feishu registration/setup API response body with "decode: %w". The HTTP call succeeded and returned a body, but the body is not valid JSON or does not match map[string]any. Callers handleSetupFeishuBegin and handleSetupFeishuPoll surface this to the user as a setup failure.

Source

Thrown at core/setup.go:251

	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
	if err != nil {
		return nil, err
	}

	var result map[string]any
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, fmt.Errorf("decode: %w", err)
	}
	return result, nil
}

// ── Weixin (ilink) QR Setup ─────────────────────────────────

func (m *ManagementServer) handleSetupWeixinBegin(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		mgmtError(w, http.StatusMethodNotAllowed, "POST only")
		return
	}

	var req struct {
		APIURL string `json:"api_url"`
	}
	_ = json.NewDecoder(r.Body).Decode(&req)

	apiBase := weixinDefaultAPIURL

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Log the raw response body (feishuRegistrationCall has it in `body`) to see what was actually returned
  2. Verify the Feishu API base URL and that the endpoint returns application/json
  3. Retry the setup flow; if behind a proxy, bypass it for the API host
  4. Check network/DNS health and Feishu service status before re-running setup

Example fix

// before
result, err := feishuRegistrationCall(ctx, "/qr/setup")
// after
result, err := feishuRegistrationCall(ctx, "/qr/setup")
if err != nil {
    slog.Error("feishu setup failed", "err", err, "endpoint", "/qr/setup")
    return fmt.Errorf("feishu setup: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

resp, err := http.Get(url)
if err == nil {
    ct := resp.Header.Get("Content-Type")
    if !strings.Contains(ct, "application/json") {
        slog.Warn("unexpected content-type from feishu api", "content_type", ct)
    }
    b, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
    if !json.Valid(b) { slog.Warn("feishu api returned invalid JSON") }
}

Type guard

func looksLikeJSON(body []byte) bool {
    t := bytes.TrimSpace(body)
    return len(t) > 0 && (t[0] == '{' || t[0] == '[')
}

Try / catch

result, err := feishuRegistrationCall(ctx, path)
if err != nil {
    var decodeErr *json.SyntaxError
    if strings.HasPrefix(err.Error(), "decode:") || errors.As(err, &decodeErr) {
        slog.Error("feishu setup: non-JSON API response (proxy/HTML page?)", "err", err)
    }
    return err
}

Prevention

When it happens

Trigger: The Feishu API endpoint returns HTML (login/error page), an empty body, a proxy interception page, or malformed JSON instead of the expected JSON object during QR setup begin/poll.

Common situations: Corporate proxy or captive portal injecting HTML; Feishu API outage returning an error page; wrong base URL configured pointing at a non-API host; intermittent network truncation of the response body.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/0914c4f0203e3330. Report an issue: GitHub.