goreleaser/goreleaser · warning
could not read from body: %w
Error message
could not read from body: %w
What it means
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.
Source
Thrown at internal/pipe/linkedin/client.go:227
req.Header.Set("Content-Type", "application/json")
resp, err := c.client.Do(req)
if err != nil {
return "", fmt.Errorf("could not POST /v2/shares: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusBadRequest {
body, _ := io.ReadAll(resp.Body)
return "", retryx.HTTP(gerrors.Wrap(
fmt.Errorf("POST /v2/shares returned %d %s", resp.StatusCode, http.StatusText(resp.StatusCode)),
gerrors.WithOutput(string(body)),
), resp)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("could not read from body: %w", err)
}
var result shareResponse
if err := json.Unmarshal(body, &result); err != nil {
return "", fmt.Errorf("could not unmarshal: %w", err)
}
// Activity URN
// URN of the activity associated with this share. Activities act as a wrapper around
// shares and articles to represent content in the LinkedIn feed. Read only.
if result.Activity == "" {
return "", errors.New("could not find 'activity' in result")
}
return fmt.Sprintf("https://www.linkedin.com/feed/update/%s", result.Activity), nil
}
View on GitHub (pinned to f5edd73956)
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.
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: verify a full request/response roundtrip works
resp, err := http.Get("https://api.linkedin.com/v2/userinfo")
if err == nil {
_, err = io.ReadAll(resp.Body) // proves bodies can be fully drained
resp.Body.Close()
}
if err != nil {
return fmt.Errorf("network cannot reliably read linkedin responses: %w", err)
} Try / catch
url, err := client.Share(ctx, msg)
if err != nil && strings.Contains(err.Error(), "could not read from body") {
// share may have succeeded; check before retrying to avoid duplicates
log.Warnf("share response body read failed, post may exist: %v", err)
return nil // or verify via feed lookup instead of reposting
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- could not POST /v2/shares: %w
- azure storage account you provided is not valid: %w
- could not get profile sub: %w
- could not get profile id: %w
- could not get profile URN: %w
AI-assisted analysis of goreleaser/goreleaser@f5edd73956 (2026-09-05).
Data as JSON: /api/errors/effde0e87906c796.
Report an issue: GitHub.