chenhg5/cc-connect · info

googlechat: marshal attachment body: %w

Error message

googlechat: marshal attachment body: %w

What it means

Returned by buildAttachmentRequest when json.Marshal fails to serialize the Chat message body carrying the attachmentDataRef. The body is built entirely from in-memory maps with an explicit thread key set by applyThread, so marshalling can only fail if a value is unencodable — practically unreachable with stock code, e.g. only if applyThread inserted an unsupported type into the thread field. It is called by postAttachment (SendImage/SendFile) and exercised by TestBuildAttachmentRequest.

Source

Thrown at platform/googlechat/googlechat.go:521

	if result.AttachmentDataRef.ResourceName == "" {
		return "", fmt.Errorf("googlechat: upload: empty resourceName in response")
	}
	return result.AttachmentDataRef.ResourceName, nil
}

// buildAttachmentRequest builds the Chat REST API URL and JSON body to post a
// message that references an already-uploaded attachment (by resource name).
// Threading behaviour mirrors buildSendRequest.
func buildAttachmentRequest(rc replyContext, resourceName string) (string, []byte, error) {
	body := map[string]any{
		"attachment": []map[string]any{
			{"attachmentDataRef": map[string]any{"resourceName": resourceName}},
		},
	}
	applyThread(body, rc)
	b, err := json.Marshal(body)
	if err != nil {
		return "", nil, fmt.Errorf("googlechat: marshal attachment body: %w", err)
	}
	return messageURL(rc), b, nil
}

// postAttachment uploads data then creates a Chat message carrying the
// attachmentDataRef. Shared by SendImage and SendFile.
func (p *Platform) postAttachment(ctx context.Context, rc replyContext, filename, mimeType string, data []byte) error {
	if rc.space == "" {
		return fmt.Errorf("googlechat: missing space in reply context")
	}
	resourceName, err := p.uploadAttachment(ctx, rc.space, filename, mimeType, data)
	if err != nil {
		return err
	}
	url, body, err := buildAttachmentRequest(rc, resourceName)
	if err != nil {
		return err
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Confirm unmodified library code; the body consists only of strings, maps, and slices.
  2. If applyThread was changed, ensure it only sets JSON-encodable values (strings/maps).
  3. Report a bug with the wrapped cause if reproducible on stock code.
Defensive patterns

Strategy: try-catch

Try / catch

if err := p.SendImage(ctx, target, path); err != nil {
    if strings.Contains(err.Error(), "marshal attachment body") {
        return fmt.Errorf("googlechat body marshal failure (library bug): %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling SendImage()/SendFile(); json.Marshal(body) returns an error — only possible if the body map contains a value json.Marshal cannot encode (e.g. a channel/func introduced via a modified applyThread).

Common situations: Effectively never hit in production with stock code; would indicate a regression where thread or other fields carry non-JSON-serializable 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/b52c8db52379d12d. Report an issue: GitHub.