chenhg5/cc-connect · error

download returned status %d

Error message

download returned status %d

What it means

The DingTalk audio download request to the resolved download URL completed but returned a non-200 HTTP status, so no audio bytes are read; typically an expired download code, auth failure, or CDN error page.

Source

Thrown at platform/dingtalk/dingtalk.go:657

	p.handler(p, msg)
}

func (p *Platform) downloadAudio(downloadCode string) ([]byte, string, error) {
	// Get download URL
	downloadURL, err := p.getDownloadURL(downloadCode)
	if err != nil {
		return nil, "", fmt.Errorf("get download URL: %w", err)
	}

	// Download audio file
	resp, err := p.httpClient.Get(downloadURL)
	if err != nil {
		return nil, "", fmt.Errorf("http get: %w", err)
	}
	defer func() { _ = resp.Body.Close() }()

	if resp.StatusCode != http.StatusOK {
		return nil, "", fmt.Errorf("download returned status %d", resp.StatusCode)
	}

	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, "", fmt.Errorf("read response: %w", err)
	}

	// Determine MIME type from Content-Type header
	mimeType := resp.Header.Get("Content-Type")
	if mimeType == "" {
		mimeType = "audio/amr" // Default to AMR if not specified
	}

	return data, mimeType, nil
}

func (p *Platform) getDownloadURL(downloadCode string) (string, error) {
	token, err := p.getAccessToken()

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Obtain a fresh download URL immediately before downloading instead of caching it across messages.
  2. Check the status code in the error to distinguish 403 (auth/permission) from 404/410 (expired URL).
  3. Verify robotCode matches the robot that received the message so the CDN authorizes the download.
  4. Retry once on 5xx; treat 4xx as non-retryable.
Defensive patterns

Strategy: retry

Validate before calling

// No pre-call API check possible; guard by freshness instead:
// only call downloadAudio with a downloadCode fetched in the current message handler,
// never one persisted from an earlier message.

Try / catch

if err != nil && strings.Contains(err.Error(), "download returned status") {
    switch {
    case strings.Contains(err.Error(), "403"):
        // permission/robot mismatch: fix robotCode, do not retry
    default:
        // expired URL or transient 5xx: fetch a fresh URL and retry once
    }
}

Prevention

When it happens

Trigger: DingTalk's file CDN or an intermediary returned 403/404/410/etc. for the downloadURL during p.httpClient.Get in downloadAudio.

Common situations: Expired download URL (very common — DingTalk URLs are short-lived); downloadCode was reused after its URL expired; permission/robot mismatch so the CDN refuses the download; CDN transient 5xx.

Related errors


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