projectdiscovery/subfinder · error
failed to marshal request body
Error message
failed to marshal request body: %w
What it means
PugRecon source marshals {"domain_name": <domain>} as the POST body. If json.Marshal fails, an Error result wrapping the original error is emitted and enumeration stops for this source. With a simple map[string]string this is effectively unreachable except in broken builds.
Solutions
- Verify the postData map contains only marshalable string values
- Rebuild from unmodified upstream pugrecon.go
- Read the wrapped %w cause in the error result to identify the offending field
Defensive patterns
Strategy: validation
Validate before calling
// postData is map[string]string — always marshalable; validate domain non-empty before building
if domain == "" { return errors.New("domain is required") } Try / catch
if err != nil {
return fmt.Errorf("failed to marshal request body: %w", err)
} Prevention
- Keep POST payload to simple string fields
- Always wrap marshal errors with %w
When it happens
Trigger: json.Marshal(postData) errors while preparing the PugRecon POST request for a domain — practically only with a modified payload structure containing non-marshalable values.
Common situations: Custom forks that added unsupported field types; corrupted toolchain builds; essentially never in stock subfinder.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
AI-assisted analysis of projectdiscovery/subfinder@7a0b91f0fa (2026-09-06).
Data as JSON: /api/errors/16094ab6d836360a.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/subscraping/sources/pugrecon/pugrecon.go:62
s.requests = 0
go func() {
defer func(startTime time.Time) {
s.timeTaken = time.Since(startTime)
close(results)
}(time.Now())
randomApiKey := subscraping.PickRandom(s.apiKeys, s.Name())
if randomApiKey == "" {
s.skipped = true
return
}
// Prepare POST request data
postData := map[string]string{"domain_name": domain}
bodyBytes, err := json.Marshal(postData)
if err != nil {
results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: fmt.Errorf("failed to marshal request body: %w", err)}
s.errors++
return
}
bodyReader := bytes.NewReader(bodyBytes)
// 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++View on GitHub (pinned to 7a0b91f0fa)