{"record":{"id":"eacc64d3032d4939","repo":"chenhg5/cc-connect","slug":"dingtalk-send-file-request-w","errorCode":null,"errorMessage":"dingtalk: send file request: %w","messagePattern":"dingtalk: send file request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":1156,"sourceCode":"\t}\n\n\tbody, err := json.Marshal(requestBody)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: marshal file message: %w\", err)\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost,\n\t\t\"https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend\",\n\t\tbytes.NewReader(body))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: create file request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"x-acs-dingtalk-access-token\", token)\n\n\tresp, err := p.httpClient.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dingtalk: send file request: %w\", err)\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\n\trespBody, _ := io.ReadAll(resp.Body)\n\tslog.Debug(\"dingtalk: oToMessages file response\", \"status\", resp.StatusCode, \"body\", string(respBody))\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"dingtalk: send file failed: status=%d, body=%s\", resp.StatusCode, string(respBody))\n\t}\n\n\tslog.Info(\"dingtalk: file message sent\", \"media_id\", mediaID, \"name\", name, \"user\", rc.senderStaffId)\n\treturn nil\n}\n\nvar _ core.FileSender = (*Platform)(nil)\n\n// SendAudio uploads audio bytes to DingTalk and sends a voice message.\n// Implements core.AudioSender interface.","sourceCodeStart":1138,"sourceCodeEnd":1174,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L1138-L1174","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the wrapped error: context.DeadlineExceeded means timeout, connection errors mean network/proxy issues","Verify connectivity: curl https://api.dingtalk.com from the host","Increase the httpClient timeout for large file uploads","Retry with backoff on transient network errors"],"exampleFix":"// before\nclient := &http.Client{}\n// after (generous timeout for file uploads)\nclient := &http.Client{Timeout: 60 * time.Second}","handlingStrategy":"retry","validationCode":"conn, err := net.DialTimeout(\"tcp\", \"api.dingtalk.com:443\", 5*time.Second); if err != nil { /* network down, skip send */ }","typeGuard":null,"tryCatchPattern":"if err := p.SendFile(ctx, rc, data, name); err != nil {\n    if errors.Is(err, context.DeadlineExceeded) { /* retry with longer deadline */ }\n    var ne net.Error; if errors.As(err, &ne) && ne.Timeout() { /* retry with backoff */ }\n}","preventionTips":["Set a generous http.Client timeout for file uploads (30-60s)","Monitor host connectivity to api.dingtalk.com","Avoid cancelling the parent context before the upload completes","Configure proxy settings explicitly if behind a corporate proxy"],"tags":["dingtalk","http","network","timeout"],"backgroundTag":"network-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}