chenhg5/cc-connect · error

get download URL: %w

Error message

get download URL: %w

What it means

downloadAudio wraps any failure from getDownloadURL with this message. The underlying cause is produced by getDownloadURL (token acquisition, request marshalling, HTTP errors), and this wrapper marks the 'obtain download URL' stage of the audio download pipeline.

Source

Thrown at platform/dingtalk/dingtalk.go:646

			senderStaffId:  data.SenderStaffId,
			messageID:      data.MsgId,
			isGroup:        data.ConversationType == "2",
		},
		Files: []core.FileAttachment{{
			MimeType: mimeType,
			Data:     fileBytes,
			FileName: fileName,
		}},
	}

	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)
	}

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the wrapped cause (%w) in logs — fix the root error (token, network, or API status).
  2. Verify client_id/client_secret are valid so getAccessToken succeeds.
  3. Retry the message handling if the cause was transient (5xx/network); DingTalk download URLs are short-lived.
  4. Check that the robotCode used matches the robot that received the message.
Defensive patterns

Strategy: try-catch

Validate before calling

// Before handling media, verify credentials work:
if err := validateDingtalkCredentials(clientID, clientSecret); err != nil { log.Fatal(err) }

Try / catch

if err != nil {
    var cause string
    if unwrapped := errors.Unwrap(err); unwrapped != nil { cause = unwrapped.Error() }
    log.Warn("dingtalk audio unavailable", "cause", cause)
    reply("Sorry, I could not fetch the voice message.")
}

Prevention

When it happens

Trigger: handleAudioMessage received a voice message and called downloadAudio(downloadCode); the inner getDownloadURL failed for any reason: expired/missing access token, network failure, or DingTalk API returning a non-200 status for /v1.0/robot/messageFiles/download.

Common situations: Expired or revoked access token; DingTalk API outage; invalid downloadCode forwarded from the webhook payload; robot code mismatch causing API rejection; network/DNS issues in the host environment.

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/975a73849548210c. Report an issue: GitHub.