{"record":{"id":"effde0e87906c796","repo":"goreleaser/goreleaser","slug":"could-not-read-from-body-w","errorCode":null,"errorMessage":"could not read from body: %w","messagePattern":"could not read from body: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/pipe/linkedin/client.go","lineNumber":227,"sourceCode":"\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresp, err := c.client.Do(req)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not POST /v2/shares: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode >= http.StatusBadRequest {\n\t\tbody, _ := io.ReadAll(resp.Body)\n\t\treturn \"\", retryx.HTTP(gerrors.Wrap(\n\t\t\tfmt.Errorf(\"POST /v2/shares returned %d %s\", resp.StatusCode, http.StatusText(resp.StatusCode)),\n\t\t\tgerrors.WithOutput(string(body)),\n\t\t), resp)\n\t}\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not read from body: %w\", err)\n\t}\n\n\tvar result shareResponse\n\tif err := json.Unmarshal(body, &result); err != nil {\n\t\treturn \"\", fmt.Errorf(\"could not unmarshal: %w\", err)\n\t}\n\n\t// Activity URN\n\t// URN of the activity associated with this share. Activities act as a wrapper around\n\t// shares and articles to represent content in the LinkedIn feed. Read only.\n\tif result.Activity == \"\" {\n\t\treturn \"\", errors.New(\"could not find 'activity' in result\")\n\t}\n\treturn fmt.Sprintf(\"https://www.linkedin.com/feed/update/%s\", result.Activity), nil\n}\n","sourceCodeStart":209,"sourceCodeEnd":243,"githubUrl":"https://github.com/goreleaser/goreleaser/blob/f5edd7395693c0c6b501dc722d445d2e86af854d/internal/pipe/linkedin/client.go#L209-L243","documentation":"This error wraps io.ReadAll failing while draining the response body of a successful (2xx) POST /v2/shares response. Reading a response body only fails on I/O problems mid-stream: the connection was reset or timed out before the full body arrived, or the body was already closed/consumed. It is rare and happens after LinkedIn already accepted the share, so the post may have succeeded even though the activity URL was lost.","triggerScenarios":"Network connection reset or context deadline expiring while reading the 2xx response body; server closing the connection prematurely (chunked encoding truncated); body previously closed by a wrapped transport.","commonSituations":"Flaky Wi-Fi/VPN dropping the connection right after LinkedIn returns 200; CI runner with aggressive idle connection timeouts; oauth2/http transport closing responses unexpectedly; extremely slow proxy truncating the response.","solutions":["Re-run the pipeline — the share may have already been posted; check your LinkedIn feed before reposting to avoid duplicates.","Read the wrapped error: 'unexpected EOF'/'connection reset' indicates a network drop — improve network stability or retry with backoff.","Check for proxies/middleboxes (corporate proxies, VPN) that truncate long-lived responses; bypass them for api.linkedin.com.","If 'http: read on closed response body' appears, it's a bug in a fork/patched transport — report upstream."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// preflight: verify a full request/response roundtrip works\nresp, err := http.Get(\"https://api.linkedin.com/v2/userinfo\")\nif err == nil {\n    _, err = io.ReadAll(resp.Body) // proves bodies can be fully drained\n    resp.Body.Close()\n}\nif err != nil {\n    return fmt.Errorf(\"network cannot reliably read linkedin responses: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"url, err := client.Share(ctx, msg)\nif err != nil && strings.Contains(err.Error(), \"could not read from body\") {\n    // share may have succeeded; check before retrying to avoid duplicates\n    log.Warnf(\"share response body read failed, post may exist: %v\", err)\n    return nil // or verify via feed lookup instead of reposting\n}","preventionTips":["Check your LinkedIn feed before retrying — the share usually posted already","Stabilize connectivity (avoid flaky VPN/proxy) during the announce step","Treat this error as ambiguous success, not a definite failure","Increase context timeouts so the body read isn't cut off mid-stream"],"tags":["go","io","network","linkedin"],"backgroundTag":"response-body-read-failed","analyzedSha":"f5edd7395693c0c6b501dc722d445d2e86af854d","analyzedAt":"2026-09-05T09:57:18.807Z","contentChangedAt":"2026-09-05T09:57:18.807Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}