projectdiscovery/subfinder · warning
failed to close response body
Error message
failed to close response body: %w
What it means
PugRecon closes the HTTP response body in a deferred func; if resp.Body.Close() returns an error, an Error result with this message is emitted. This is a defensive check — close errors on response bodies rarely indicate lost data, since the body was already fully consumed or discarded.
Solutions
- Check the wrapped %w cause — if it's a connection-reset, treat the response as unreliable and retry
- Verify the status code handling already captured the real failure earlier in the flow
- If noise-only, run the source again; the error is typically transient
- Avoid custom RoundTrippers that surface spurious close errors
Example fix
// before
if err := resp.Body.Close(); err != nil {
results <- subscraping.Result{... Error: fmt.Errorf("failed to close response body: %w", err)}
}
// after
if err := resp.Body.Close(); err != nil && resp.StatusCode == http.StatusOK {
results <- subscraping.Result{... Error: fmt.Errorf("failed to close response body: %w", err)}
} Defensive patterns
Strategy: try-catch
Try / catch
defer func() {
if cerr := resp.Body.Close(); cerr != nil {
log.Printf("non-fatal close error: %v", cerr) // don't fail the run for close errors
}
}() Prevention
- Treat close errors as non-fatal when the body was already read
- Check the wrapped cause only if the status was OK and data looks suspect
- Avoid custom transports that raise spurious close errors
When it happens
Trigger: The deferred resp.Body.Close() call returns non-nil after the PugRecon API POST completes — e.g. some transports/proxies report errors on close after connection resets.
Common situations: Connection torn down abruptly mid/close by proxy or server; custom HTTP transports returning close errors; usually benign noise alongside a real network issue.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of projectdiscovery/subfinder@7a0b91f0fa (2026-09-06).
Data as JSON: /api/errors/73ba90d593c55928.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/subscraping/sources/pugrecon/pugrecon.go:86
// Prepare headers
headers := map[string]string{
"Authorization": "Bearer " + randomApiKey,
"Content-Type": "application/json",
"Accept": "application/json",
}
apiURL := "https://pugrecon.com/api/v1/domains"
s.requests++
resp, err := session.HTTPRequest(ctx, http.MethodPost, apiURL, "", headers, bodyReader, subscraping.BasicAuth{}) // Use HTTPRequest for full header control
if err != nil {
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
s.errors++
session.DiscardHTTPResponse(resp)
return
}
defer func() {
if err := resp.Body.Close(); err != nil {
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: fmt.Errorf("failed to close response body: %w", err)}
s.errors++
}
}()
if resp.StatusCode != http.StatusOK {
errorMsg := fmt.Sprintf("received status code %d", resp.StatusCode)
// Attempt to read error message from body if possible
var apiResp pugreconAPIResponse
if json.NewDecoder(resp.Body).Decode(&apiResp) == nil && apiResp.Message != "" {
errorMsg = fmt.Sprintf("%s: %s", errorMsg, apiResp.Message)
}
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: fmt.Errorf("%s", errorMsg)}
s.errors++
return
}
var response pugreconAPIResponse
err = json.NewDecoder(resp.Body).Decode(&response)View on GitHub (pinned to 7a0b91f0fa)