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, errView on GitHub (pinned to 4000b2338a)
Solutions
- Log the raw body (truncateForLog) to see what was returned
- Verify the bot session is valid and re-authenticate
- Update getUploadURLResponse to the current iLink schema
- 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
- Keep getUploadURLResponse fields updated with iLink API changes
- Re-authenticate when uploads suddenly fail with unmarshal errors
- Log raw bodies (truncated) for every upload failure
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
- get_bot_qrcode json: %w
- get_qrcode_status json: %w
- invalid json response: %w
- weixin: getUpdates json: %w
- weixin: sendMessage: response json: %w: %s
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/693bc186de0d60b4.
Report an issue: GitHub.