chenhg5/cc-connect · error

googlechat: upload: build request: %w

Error message

googlechat: upload: build request: %w

What it means

Returned by uploadAttachment when http.NewRequestWithContext fails to construct the POST request to the Chat media upload endpoint. This only fails if the URL fails http.ParseRequestURI parsing or the method is invalid; since the URL is chatUploadBase + space + a fixed suffix, a malformed space value (containing spaces, control characters, or a bad scheme) is the realistic trigger. It surfaces via postAttachment from SendImage/SendFile.

Source

Thrown at platform/googlechat/googlechat.go:480

	if err := json.NewEncoder(metaPart).Encode(map[string]string{"filename": filename}); err != nil {
		return "", fmt.Errorf("googlechat: upload: encode metadata: %w", err)
	}

	mediaPart, err := mw.CreatePart(textproto.MIMEHeader{"Content-Type": {mimeType}})
	if err != nil {
		return "", fmt.Errorf("googlechat: upload: create media part: %w", err)
	}
	if _, err := mediaPart.Write(data); err != nil {
		return "", fmt.Errorf("googlechat: upload: write media: %w", err)
	}
	if err := mw.Close(); err != nil {
		return "", fmt.Errorf("googlechat: upload: finalize multipart body: %w", err)
	}

	uploadURL := chatUploadBase + space + "/attachments:upload?uploadType=multipart"
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, uploadURL, buf)
	if err != nil {
		return "", fmt.Errorf("googlechat: upload: build request: %w", err)
	}
	req.Header.Set("Content-Type", "multipart/related; boundary="+mw.Boundary())

	resp, err := p.doRequest(req)
	if err != nil {
		return "", err
	}
	defer func() {
		if err := resp.Body.Close(); err != nil {
			slog.Warn("googlechat: close upload response body", "error", err)
		}
	}()

	var result struct {
		AttachmentDataRef struct {
			ResourceName string `json:"resourceName"`
		} `json:"attachmentDataRef"`
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Verify the configured Google Chat space ID matches the format spaces/<alphanumeric-id> with no whitespace.
  2. Print/log the composed upload URL (chatUploadBase + space) before the request to inspect the malformed portion.
  3. Trim whitespace/newlines from the space config value at load time.
  4. Obtain the space resource name via the Chat API spaces.list and use the exact resourceName.

Example fix

// before
space := cfg.Space // may contain whitespace
// after
space = strings.TrimSpace(cfg.Space)
if !strings.HasPrefix(space, "spaces/") {
    return fmt.Errorf("invalid space %q", space)
}
Defensive patterns

Strategy: validation

Validate before calling

// validate space resource name before sending
space = strings.TrimSpace(cfg.Space)
if !strings.HasPrefix(space, "spaces/") || strings.ContainsAny(space, " \t\r\n\x00") {
    return fmt.Errorf("invalid googlechat space %q: want spaces/<id>", cfg.Space)
}

Type guard

func isValidSpaceName(s string) bool {
    s = strings.TrimSpace(s)
    if !strings.HasPrefix(s, "spaces/") { return false }
    id := strings.TrimPrefix(s, "spaces/")
    return id != "" && strings.IndexFunc(id, func(r rune) bool {
        return r < '!' || r > '~'
    }) == -1
}

Prevention

When it happens

Trigger: Calling SendImage()/SendFile() where the resolved space resource name (e.g. spaces/AAA...) is empty or contains characters that break URL parsing — for example an unconfigured or misparsed space ID.

Common situations: Config mistakes: missing or wrong space ID in config.toml; a placeholder like "YOUR_SPACE_ID" with special characters; accidental whitespace or newlines in the configured space name.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


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