chenhg5/cc-connect · error

dingtalk: create audio request: %w

Error message

dingtalk: create audio request: %w

What it means

This error wraps a failure from http.NewRequestWithContext when constructing the audio voice-message POST to https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend. As with the file equivalent, the URL and method are hardcoded constants, so construction failure is nearly impossible; it exists as a guard.

Source

Thrown at platform/dingtalk/dingtalk.go:1274

	requestBody := map[string]interface{}{
		"robotCode": p.robotCode,
		"userIds":   []string{rc.senderStaffId},
		"msgKey":    "sampleAudio",
		"msgParam":  msgParamJSON,
	}

	body, err := json.Marshal(requestBody)
	if err != nil {
		return fmt.Errorf("dingtalk: marshal audio message: %w", err)
	}

	slog.Debug("dingtalk: sending voice via oToMessages API", "media_id", mediaID, "duration", durationMs, "user_id", rc.senderStaffId)

	req, err := http.NewRequestWithContext(ctx, http.MethodPost,
		"https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend",
		bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("dingtalk: create audio request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-acs-dingtalk-access-token", token)

	resp, err := p.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("dingtalk: send audio request: %w", err)
	}
	defer func() { _ = resp.Body.Close() }()

	respBody, _ := io.ReadAll(resp.Body)
	slog.Debug("dingtalk: oToMessages API response", "status", resp.StatusCode, "body", string(respBody))

	if resp.StatusCode != 200 {
		return fmt.Errorf("dingtalk: send audio failed: status=%d, body=%s", resp.StatusCode, string(respBody))
	}

	slog.Info("dingtalk: voice message sent successfully", "media_id", mediaID, "conversation_id", rc.conversationId)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the wrapped error for the URL-parse failure
  2. If the endpoint is now configurable, validate it with url.Parse before use
  3. Retry if caused by transient resource exhaustion

Example fix

// before
req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.audioEndpoint, bytes.NewReader(body))
// after
if _, err := url.Parse(p.audioEndpoint); err != nil { return fmt.Errorf("dingtalk: invalid audio endpoint: %w", err) }
req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.audioEndpoint, bytes.NewReader(body))
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := url.Parse("https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend"); err != nil { /* fail fast */ }

Try / catch

if err := p.SendAudio(ctx, rc, audio, format); err != nil && strings.Contains(err.Error(), "create audio request") { log.Fatalf("audio request construction failed: %v", err) }

Prevention

When it happens

Trigger: http.NewRequestWithContext failing while building the sampleAudio request — only under abnormal conditions such as memory exhaustion or if the URL construction is modified to use an invalid dynamic value.

Common situations: Not hit in practice with stock code; appears if developers parameterize the endpoint with a malformed URL.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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