chenhg5/cc-connect · error

dingtalk: send file request: %w

Error message

dingtalk: send file request: %w

What it means

This error wraps a failure from httpClient.Do when executing the file-send request to DingTalk's oToMessages batchSend endpoint. It indicates the HTTP round trip itself failed: DNS resolution, TCP connect, TLS, timeouts, or context cancellation. The request was built fine but never got a response.

Source

Thrown at platform/dingtalk/dingtalk.go:1156

	}

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

	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 file 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 file request: %w", err)
	}
	defer func() { _ = resp.Body.Close() }()

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

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

	slog.Info("dingtalk: file message sent", "media_id", mediaID, "name", name, "user", rc.senderStaffId)
	return nil
}

var _ core.FileSender = (*Platform)(nil)

// SendAudio uploads audio bytes to DingTalk and sends a voice message.
// Implements core.AudioSender interface.

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check the wrapped error: context.DeadlineExceeded means timeout, connection errors mean network/proxy issues
  2. Verify connectivity: curl https://api.dingtalk.com from the host
  3. Increase the httpClient timeout for large file uploads
  4. Retry with backoff on transient network errors

Example fix

// before
client := &http.Client{}
// after (generous timeout for file uploads)
client := &http.Client{Timeout: 60 * time.Second}
Defensive patterns

Strategy: retry

Validate before calling

conn, err := net.DialTimeout("tcp", "api.dingtalk.com:443", 5*time.Second); if err != nil { /* network down, skip send */ }

Try / catch

if err := p.SendFile(ctx, rc, data, name); err != nil {
    if errors.Is(err, context.DeadlineExceeded) { /* retry with longer deadline */ }
    var ne net.Error; if errors.As(err, &ne) && ne.Timeout() { /* retry with backoff */ }
}

Prevention

When it happens

Trigger: Calling SendFile when the network to api.dingtalk.com is down/unreachable, the context is cancelled mid-request, the HTTP client timeout expires, TLS handshake fails, or a proxy blocks the connection.

Common situations: Corporate firewalls/proxies blocking api.dingtalk.com, no internet on the host, DNS misconfiguration, very slow networks exceeding the client timeout, or the parent context being cancelled by an upstream deadline.

Related errors


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