chenhg5/cc-connect · error

weixin: getUploadUrl json: %w

Error message

weixin: getUploadUrl json: %w

What it means

getUploadURL requests a CDN upload address via ilink/bot/getuploadurl and decodes the reply into getUploadURLResponse. This error wraps a json.Unmarshal failure — the body is not valid JSON or does not fit the struct, typically an HTML error page or an API schema change.

Source

Thrown at platform/weixin/client.go:204

		return fmt.Errorf("weixin: sendMessage: ret=%d errcode=%d errmsg=%s",
			resp.Ret, resp.Errcode, resp.Errmsg)
	}
	return nil
}

func (c *apiClient) getUploadURL(ctx context.Context, req getUploadURLRequest) (*getUploadURLResponse, error) {
	req.BaseInfo = baseInfo{ChannelVersion: channelVersion}
	payload, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}
	raw, err := c.post(ctx, "ilink/bot/getuploadurl", payload, 0, "getUploadUrl")
	if err != nil {
		return nil, err
	}
	var out getUploadURLResponse
	if err := json.Unmarshal(raw, &out); err != nil {
		return nil, fmt.Errorf("weixin: getUploadUrl json: %w", err)
	}
	// 兼容微信 iLink API 变更:新版返回 upload_full_url 而非 upload_param
	// upload_full_url 是完整的 CDN 上传地址,可独立作为成功路径
	if strings.TrimSpace(out.UploadParam) == "" && strings.TrimSpace(out.UploadFullURL) == "" {
		return nil, fmt.Errorf("weixin: getUploadUrl: empty upload_param and upload_full_url in %s", truncateForLog(raw, 512))
	}
	return &out, nil
}

func (c *apiClient) getConfig(ctx context.Context, userID, contextToken string) (*getConfigResp, error) {
	req := getConfigReq{
		UserID:       userID,
		ContextToken: contextToken,
		BaseInfo:     baseInfo{ChannelVersion: channelVersion},
	}
	payload, err := json.Marshal(req)
	if err != nil {
		return nil, err

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Log the raw body (truncateForLog) to see what was returned
  2. Verify the bot session is valid and re-authenticate
  3. Update getUploadURLResponse to the current iLink schema
  4. Check for intermediaries (proxy/WAF) corrupting the response
Defensive patterns

Strategy: try-catch

Validate before calling

if len(bytes.TrimSpace(raw)) == 0 { return errors.New("weixin: empty getuploadurl body") }

Try / catch

resp, err := getUploadURL(ctx, req)
if err != nil {
	if strings.Contains(err.Error(), "getUploadUrl json") {
		slog.Error("weixin: upload-url response not JSON", "err", err)
		return fallbackUploadPath()
	}
	return err
}

Prevention

When it happens

Trigger: The getuploadurl endpoint returns non-JSON (proxy HTML, gateway error) or a new schema whose fields no longer decode into getUploadURLResponse (e.g. type changes causing UnmarshalTypeError).

Common situations: WeChat iLink API evolution (the code already works around upload_param→upload_full_url); proxies rewriting responses; authenticated session expired so the server returns an error page.

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/693bc186de0d60b4. Report an issue: GitHub.