chenhg5/cc-connect · error

webex: downloadFile status %d

Error message

webex: downloadFile status %d

What it means

DownloadFile fetches an attachment over the Webex REST API. After retries, any HTTP status other than 200 aborts the download and this error wraps the status code. It means the request reached Webex but the response was not a successful download.

Source

Thrown at platform/webex/client.go:190

	defer func() { _ = resp.Body.Close() }()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("webex: getMessage status %d", resp.StatusCode)
	}
	var m message
	if err := json.NewDecoder(resp.Body).Decode(&m); err != nil {
		return nil, err
	}
	return &m, nil
}

func (c *httpClient) DownloadFile(ctx context.Context, url string) (*downloadedFile, error) {
	resp, err := c.doWithRetry(ctx, http.MethodGet, url, nil, "", "webex: downloadFile")
	if err != nil {
		return nil, err
	}
	defer func() { _ = resp.Body.Close() }()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("webex: downloadFile status %d", resp.StatusCode)
	}
	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	f := &downloadedFile{Data: data, MimeType: resp.Header.Get("Content-Type")}
	if cd := resp.Header.Get("Content-Disposition"); cd != "" {
		if _, params, err := mime.ParseMediaType(cd); err == nil {
			f.FileName = params["filename"]
		}
	}
	return f, nil
}

func (c *httpClient) PostMessage(ctx context.Context, roomID, parentID, markdown string) error {
	body := map[string]string{"roomId": roomID, "markdown": markdown}
	if parentID != "" {
		body["parentId"] = parentID

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Log the status code to identify the cause: 401/403 → fix the bot token, 404 → the attachment is gone
  2. Check the bot token validity and scopes; regenerate if expired or revoked
  3. Add caller-side handling: for 404, treat as non-retryable and skip the file; for 5xx, retry later
  4. Verify the URL passed to DownloadFile came directly from the message payload, not a stale copy

Example fix

// before
f, err := client.DownloadFile(ctx, staleURL)
// after
f, err := client.DownloadFile(ctx, msg.Files[0])
if err != nil {
    var httpErr interface{ Error() string }
    if strings.Contains(err.Error(), "status 404") {
        return nil // attachment expired, skip
    }
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

if u == "" || !strings.HasPrefix(u, "http") { skip download }

Try / catch

f, err := client.DownloadFile(ctx, url)
if err != nil {
    if strings.Contains(err.Error(), "status 404") { return nil /* expired attachment */ }
    return fmt.Errorf("download attachment: %w", err)
}

Prevention

When it happens

Trigger: Calling DownloadFile for an attachment URL that returns 401 (expired/invalid token), 404 (deleted or expired attachment), or 403/5xx from the Webex content API.

Common situations: Bots trying to re-download old attachments whose content URLs expired; token revoked or lacking scope; transient Webex CDN errors surfacing as 502/503 after retries.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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