chenhg5/cc-connect · info

marshal payload: %w

Error message

marshal payload: %w

What it means

This error wraps a failure from json.Marshal when serializing the createAndDeliver request payload in platform/dingtalk/card.go:111 (createAICard, called by CreateStreamingCard). The payload is a map[string]any of card template ID, outTrackId, cardData, and delivery models, all strings/numbers, so marshal failure is nearly impossible in practice and indicates an internal invariant violation (e.g. an unsupported value type such as a channel or func injected into the payload).

Source

Thrown at platform/dingtalk/card.go:111

		"openSpaceId":           openSpaceId,
		"userIdType":            1,
	}

	// Set delivery model based on conversation type
	if isGroup {
		payload["imGroupOpenDeliverModel"] = map[string]any{
			"robotCode": p.robotCode,
		}
	} else {
		payload["imRobotOpenDeliverModel"] = map[string]any{
			"spaceType": "IM_ROBOT",
			"robotCode": p.robotCode,
		}
	}

	bodyBytes, err := json.Marshal(payload)
	if err != nil {
		return nil, fmt.Errorf("marshal payload: %w", err)
	}

	reqCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(reqCtx, http.MethodPost,
		"https://api.dingtalk.com/v1.0/card/instances/createAndDeliver",
		bytes.NewReader(bodyBytes))
	if err != nil {
		return nil, fmt.Errorf("create request: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-acs-dingtalk-access-token", token)

	slog.Debug("dingtalk: creating AI card", "outTrackId", outTrackId, "isGroup", isGroup)

	resp, err := p.httpClient.Do(req)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the payload values passed to createAICard; log fmt.Sprintf("%T", v) for each payload entry to find the non-serializable value
  2. Ensure cardTemplateID, robotCode, conversationId, and senderStaffId are plain strings from config, not custom types with failing MarshalJSON
  3. Since all stock values are JSON-safe, treat this as a bug and report it with the wrapped %w error chain

Example fix

// before (custom type breaks marshal)
type templateID struct{ ID string }
func (t templateID) MarshalJSON() ([]byte, error) { return nil, errors.New("unsupported") }
// after
var cardTemplateID string = "your-template-id"
Defensive patterns

Strategy: validation

Validate before calling

if b, err := json.Marshal(payload); err != nil {
	return fmt.Errorf("dingtalk payload not serializable: %w", err)
}

Try / catch

if _, err := createCard(ctx, rc); err != nil {
	var marshalErr error
	if errors.Unwrap(err) != nil && strings.Contains(err.Error(), "marshal payload") {
		marshalErr = err
		log.Printf("payload serialization bug: %v", marshalErr)
	}
}

Prevention

When it happens

Trigger: json.Marshal returns an error while serializing the createAndDeliver payload map; this only happens if a value in the payload map is of a type json cannot encode (func, chan, or a type with a failing MarshalJSON method).

Common situations: Custom builds where cardTemplateID, robotCode, or cardData values were replaced with unsupported custom types (e.g. a wrapper type with a panicking/failing MarshalJSON); practically never seen with stock string/number config values.

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


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