{"record":{"id":"441d04fa9207ff48","repo":"micro/go-micro","slug":"failed-to-read-response-w","errorCode":null,"errorMessage":"failed to read response: %w","messagePattern":"failed to read response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ai/anthropic/anthropic.go","lineNumber":381,"sourceCode":"\t\treturn nil, nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\n\t// Set headers\n\thttpReq.Header.Set(\"Content-Type\", \"application/json\")\n\thttpReq.Header.Set(\"x-api-key\", p.opts.APIKey)\n\thttpReq.Header.Set(\"anthropic-version\", \"2023-06-01\")\n\n\t// Make request\n\thttpResp, err := http.DefaultClient.Do(httpReq)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"API request failed: %w\", err)\n\t}\n\tdefer httpResp.Body.Close()\n\n\t// Read response\n\trespBody, err := io.ReadAll(httpResp.Body)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"failed to read response: %w\", err)\n\t}\n\tif httpResp.StatusCode != http.StatusOK {\n\t\treturn nil, nil, ai.NewHTTPError(httpResp, respBody)\n\t}\n\n\t// Parse response\n\tvar anthropicResp struct {\n\t\tContent []struct {\n\t\t\tType  string          `json:\"type\"`\n\t\t\tText  string          `json:\"text\"`\n\t\t\tID    string          `json:\"id\"`\n\t\t\tName  string          `json:\"name\"`\n\t\t\tInput json.RawMessage `json:\"input\"`\n\t\t} `json:\"content\"`\n\t\tStopReason string `json:\"stop_reason\"`\n\t}\n\n\tif err := json.Unmarshal(respBody, &anthropicResp); err != nil {","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/micro/go-micro/blob/24529f140421a11a33b6999ab7944f2021cfd69c/ai/anthropic/anthropic.go#L363-L399","documentation":"Returned by Provider.callAPI when reading the response body with io.ReadAll fails after the HTTP request completed. This is rare and indicates the connection was reset or dropped mid-body read — the response headers arrived but the body could not be fully consumed.","triggerScenarios":"io.ReadAll(httpResp.Body) errors: connection reset by peer mid-response, network interruption while transferring the body, proxy terminating the connection early, or an abruptly closed keep-alive connection.","commonSituations":"Flaky networks or NAT timeouts dropping long-lived connections, load balancers with short idle timeouts, VPN instability, or proxies closing connections on slow Anthropic responses.","solutions":["Retry the request — transient body-read resets usually succeed on a second attempt with fresh connection.","Set a custom http.Client with sensible Timeout and DisableKeepAlives or Transport settings to avoid stale reused connections.","Rule out intermediary proxies/VPNs by testing on the same host with curl.","Increase load balancer/proxy idle timeouts if the failures correlate with slow responses."],"exampleFix":"// before\nresp, err := provider.Generate(ctx, prompt)\nif err != nil { return err }\n// after\nresp, err := provider.Generate(ctx, prompt)\nif err != nil && isTransientNetErr(err) { resp, err = provider.Generate(ctx, prompt) } // one retry","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var resp *ai.Response\nvar err error\nfor i := 0; i < 2; i++ { // one retry for transient body-read resets\n\tresp, err = provider.Generate(ctx, prompt)\n\tif err == nil || !errors.Is(err, io.ErrUnexpectedEOF) && !strings.Contains(err.Error(), \"failed to read response\") { break }\n\ttime.Sleep(250*time.Millisecond)\n}","preventionTips":["Retry transient body-read failures once with a short backoff","Avoid stale keep-alive connections on flaky networks (tune Transport)","Check proxy/LB idle timeouts against slow LLM responses","Stabilize the network path (VPN/NAT) before blaming the library"],"tags":["network","http","io","anthropic"],"backgroundTag":"connection-reset","analyzedSha":"24529f140421a11a33b6999ab7944f2021cfd69c","analyzedAt":"2026-09-01T02:52:24.923Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}