chenhg5/cc-connect · error

weixin: getUploadUrl: empty upload_param and upload_full_url

Error message

weixin: getUploadUrl: empty upload_param and upload_full_url in %s

What it means

After decoding getuploadurl's response, the client validates it actually contains an upload address. WeChat's iLink API changed from returning upload_param to upload_full_url; if BOTH are empty, no usable CDN upload target exists and the client refuses to continue with a body snippet for debugging.

Source

Thrown at platform/weixin/client.go:209

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
	}
	raw, err := c.post(ctx, "ilink/bot/getconfig", payload, 0, "getConfig")
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Log/inspect the returned body snippet in the error to find the actual field names
  2. Update getUploadURLResponse to parse the new upload-address field and treat it as valid
  3. Re-authenticate/refresh the ticket if the API returns empty addresses for stale sessions
  4. Retry once before surfacing the error, in case of transient degradation

Example fix

// before
if strings.TrimSpace(out.UploadParam) == "" && strings.TrimSpace(out.UploadFullURL) == "" {
	return nil, fmt.Errorf("weixin: getUploadUrl: empty upload_param and upload_full_url in %s", ...)
}
// after: accept a newly introduced field too
if strings.TrimSpace(out.UploadParam) == "" && strings.TrimSpace(out.UploadFullURL) == "" && strings.TrimSpace(out.UploadURL) == "" {
	return nil, fmt.Errorf("weixin: getUploadUrl: no upload address in %s", truncateForLog(raw, 512))
}
Defensive patterns

Strategy: fallback

Validate before calling

if strings.TrimSpace(resp.UploadParam) == "" && strings.TrimSpace(resp.UploadFullURL) == "" { /* treat as failure before calling CDN */ }

Type guard

func hasUploadAddress(r *getUploadURLResponse) bool {
	return r != nil && (strings.TrimSpace(r.UploadParam) != "" || strings.TrimSpace(r.UploadFullURL) != "")
}

Try / catch

addr, err := getUploadURL(ctx, req)
if err != nil || !hasUploadAddress(addr) {
	slog.Warn("weixin: no upload address; retrying once", "err", err)
	addr, err = getUploadURL(ctx, req)
	if err != nil { return err }
}

Prevention

When it happens

Trigger: The API response decodes fine but lacks both UploadParam and UploadFullURL — server-side rejection embedded in a 200 body, degraded API response, or yet another schema change introducing a new field name.

Common situations: WeChat iLink API protocol drift (the exact scenario this guard was added for); expired ticket yielding an empty success body; regional API versions with different field names.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — 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/2e62473baedb111a. Report an issue: GitHub.