chenhg5/cc-connect · error
dingtalk: send image request: %w
Error message
dingtalk: send image request: %w
What it means
Returned by SendImage when the actual HTTP POST to DingTalk's oToMessages batchSend API fails at the transport level (connection error, timeout, TLS failure). It wraps the underlying net/http error, so the root cause is in the wrapped message.
Source
Thrown at platform/dingtalk/dingtalk.go:1061
}
body, err := json.Marshal(requestBody)
if err != nil {
return fmt.Errorf("dingtalk: marshal image 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 image 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 image request: %w", err)
}
defer func() { _ = resp.Body.Close() }()
respBody, _ := io.ReadAll(resp.Body)
slog.Debug("dingtalk: oToMessages image response", "status", resp.StatusCode, "body", string(respBody))
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("dingtalk: send image failed: status=%d, body=%s", resp.StatusCode, string(respBody))
}
slog.Info("dingtalk: image message sent", "media_id", mediaID, "user", rc.senderStaffId)
return nil
}
var _ core.ImageSender = (*Platform)(nil)
var _ core.StreamingCardPlatform = (*Platform)(nil)
var _ core.ReplyContextReconstructor = (*Platform)(nil)
var _ core.TypingIndicator = (*Platform)(nil)View on GitHub (pinned to 4000b2338a)
Solutions
- Inspect the wrapped error for the transport cause (dial timeout, TLS, DNS)
- Verify egress connectivity: curl https://api.dingtalk.com from the host
- Increase p.httpClient timeout if requests are large or the network is slow
- Retry with backoff on transient errors (net.Error, timeouts); check DingTalk status page during outages
Example fix
// before cfg.HTTPClient.Timeout = 2 * time.Second // after cfg.HTTPClient.Timeout = 15 * time.Second // allow for slow DingTalk API responses
Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", "api.dingtalk.com:443", 5*time.Second)
if err != nil {
return fmt.Errorf("no egress to api.dingtalk.com: %w", err)
}
conn.Close() Try / catch
var ne net.Error
if err := p.SendImage(ctx, rc, img); err != nil {
if errors.As(err, &ne) && ne.Timeout() {
// transient: retry with backoff
}
return err
} Prevention
- Configure a sane HTTP client timeout (10-30s)
- Retry transient transport errors with exponential backoff
- Monitor host egress/DNS health; alert on api.dingtalk.com unreachable
When it happens
Trigger: Network outage or DNS failure reaching api.dingtalk.com; request timeout from p.httpClient; TLS interception/proxy issues; context cancelled mid-request.
Common situations: Corporate proxy blocking api.dingtalk.com; HTTP client timeout too small for large deployments; container losing egress; DingTalk API regional outage.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- do request: %w
- do request: %w
- dingtalk: emotion request: %w
- dingtalk: send file request: %w
- dingtalk: send audio request: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/75e3aa7dc5311c08.
Report an issue: GitHub.