{"record":{"id":"6465cef05f3a07b2","repo":"chenhg5/cc-connect","slug":"do-request-w-6465ce","errorCode":null,"errorMessage":"do request: %w","messagePattern":"do request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/dingtalk/dingtalk.go","lineNumber":703,"sourceCode":"\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"marshal request: %w\", err)\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n\tdefer cancel()\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost,\n\t\t\"https://api.dingtalk.com/v1.0/robot/messageFiles/download\",\n\t\tbytes.NewReader(bodyBytes))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"create request: %w\", err)\n\t}\n\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(\"do request: %w\", err)\n\t}\n\tdefer func() { _ = resp.Body.Close() }()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"api returned status %d\", resp.StatusCode)\n\t}\n\n\tvar result downloadResponse\n\tif err := json.NewDecoder(resp.Body).Decode(&result); err != nil {\n\t\treturn \"\", fmt.Errorf(\"decode response: %w\", err)\n\t}\n\n\tif result.DownloadUrl == \"\" {\n\t\treturn \"\", fmt.Errorf(\"empty downloadUrl in response\")\n\t}\n\n\treturn result.DownloadUrl, nil\n}","sourceCodeStart":685,"sourceCodeEnd":721,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/dingtalk/dingtalk.go#L685-L721","documentation":"getDownloadURL wraps a transport-level failure of the POST to DingTalk's messageFiles/download API. The request was built and sent but p.httpClient.Do returned an error: connection failure, DNS, TLS, or the 30-second context timeout expired.","triggerScenarios":"Called from handleImageMessage, handleFileMessage, or downloadAudio; p.httpClient.Do(req) errored — e.g. no outbound network to api.dingtalk.com, proxy blocking, or context.WithTimeout(30s) deadline exceeded.","commonSituations":"Corporate firewall/proxy blocking api.dingtalk.com; DNS resolution failure; DingTalk API slow or unreachable; sustained network outage; extremely slow host causing the 30s timeout to fire.","solutions":["Test connectivity to https://api.dingtalk.com from the host (curl the endpoint).","Check proxy/firewall rules and HTTP(S)_PROXY environment variables affecting the Go HTTP client.","Check the wrapped cause for 'context deadline exceeded' — if timeouts recur, review network latency or proxying to DingTalk.","Retry with backoff for transient network errors."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Startup connectivity check:\nconn, err := net.DialTimeout(\"tcp\", \"api.dingtalk.com:443\", 5*time.Second)\nif err != nil { log.Fatal(\"cannot reach api.dingtalk.com: \", err) }\nconn.Close()","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        log.Warn(\"dingtalk download API timed out\")\n    } else {\n        log.Warn(\"dingtalk download API unreachable\", \"err\", err)\n    }\n    return retryWithBackoff(2) // transient network issue\n}","preventionTips":["Allow outbound HTTPS to api.dingtalk.com in firewalls/proxies","Set HTTP(S)_PROXY correctly if the host requires a proxy","Use bounded retries with backoff for transient network faults","Monitor host DNS and egress health"],"tags":["dingtalk","http","network","timeout","api"],"backgroundTag":"http-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"}