chenhg5/cc-connect · error
dingtalk: marshal proactive message: %w
Error message
dingtalk: marshal proactive message: %w
What it means
This error wraps a json.Marshal failure while serializing the proactive message payload (robotCode, userIds/conversationId, msgKey, msgParam) into the HTTP request body. It indicates the request struct could not be converted to JSON, which for these plain types almost always means an unexpected value ended up in the payload (e.g. an unsupported type slipped into msgParam or a nested field).
Source
Thrown at platform/dingtalk/dingtalk.go:1680
"msgParam": string(msgParam),
}
} else if rc.senderStaffId != "" {
// Direct message via /v1.0/robot/oToMessages/batchSend
apiURL = "https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend"
msgParam, _ := json.Marshal(map[string]string{"title": cardTitleFromContent(content), "text": content})
requestBody = map[string]any{
"robotCode": p.robotCode,
"userIds": []string{rc.senderStaffId},
"msgKey": "sampleMarkdown",
"msgParam": string(msgParam),
}
} else {
return fmt.Errorf("dingtalk: proactive send requires conversationId (group) or senderStaffId (direct)")
}
body, err := json.Marshal(requestBody)
if err != nil {
return fmt.Errorf("dingtalk: marshal proactive message: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(body))
if err != nil {
return fmt.Errorf("dingtalk: create proactive request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-acs-dingtalk-access-token", token)
resp, err := p.httpClient.Do(req)
if err != nil {
return fmt.Errorf("dingtalk: proactive send request: %w", err)
}
defer func() { _ = resp.Body.Close() }()
respBody, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("dingtalk: proactive send failed: status=%d, body=%s", resp.StatusCode, string(respBody))View on GitHub (pinned to 4000b2338a)
Solutions
- Inspect the wrapped error (%w) to see the exact Go type that failed to marshal.
- Ensure msgParam is produced via json.Marshal of a plain map/struct (string), not raw dynamic values.
- Log the requestBody structure (with token redaction) in a debug build to find the offending field.
- If the marshal error persists with plain types, report it as a bug — stdlib json.Marshal cannot fail on map[string]any of strings/slices.
Example fix
// before
msgParam, _ := somethingDynamic() // may be non-serializable
requestBody["msgParam"] = msgParam
// after
msgParamBytes, err := json.Marshal(map[string]string{"content": content})
if err != nil {
return fmt.Errorf("dingtalk: build msgParam: %w", err)
}
requestBody["msgParam"] = string(msgParamBytes) Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := json.Marshal(requestBody); err != nil {
slog.Error("payload not serializable", "err", err)
} Try / catch
if err := p.Send(ctx, rc, msg); err != nil {
if strings.Contains(err.Error(), "marshal proactive message") {
slog.Error("proactive payload invalid", "err", err)
}
} Prevention
- Keep the request body to JSON-safe types (string, map, slice)
- Always build msgParam via json.Marshal of a plain map
- Never insert dynamic values like channels or funcs into the request map
When it happens
Trigger: json.Marshal(requestBody) returns an error immediately after building the proactive-send request map in the proactive send function.
Common situations: Embedding a non-JSON-serializable value (channel, func, cyclic structure) into the request body via custom options; corrupted msgParam bytes assembly upstream.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- marshal payload: %w
- marshal request: %w
- dingtalk: marshal emotion request: %w
- dingtalk: marshal image message: %w
- dingtalk: marshal file message: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/2125c938faa395dd.
Report an issue: GitHub.