projectdiscovery/subfinder · error

%s, %s

Error message

%s, %s

What it means

The AlienVault source reports upstream API errors by combining the response's 'detail' and 'error' fields into a single error Result: fmt.Errorf("%s, %s", response.Detail, response.Error). This surfaces AlienVault's own API error message to the caller as a scraping Result of type Error.

Solutions

  1. Set a valid OTX API key in the subfinder provider config ($HOME/.config/subfinder/provider-config.yaml)
  2. Check your OTX account quota/usage and retry after backoff
  3. Retry later if OTX is having an outage; check OTX status
  4. Inspect the error text: the detail message usually names the exact problem (auth, quota, bad query)
Defensive patterns

Strategy: try-catch

Try / catch

for result := range results {
    if result.Type == subscraping.Error {
        gologger.Warning().Msgf("alienvault: %v", result.Error)
        continue
    }
    // process result
}

Prevention

When it happens

Trigger: AlienVault OTX API returns a JSON body where response.Error is non-empty — typically invalid/missing OTX API key, or the API rejecting the request (quota, bad request).

Common situations: No OTX API key configured or key expired; hitting OTX rate limits; OTX API temporary outages or schema changes producing error fields in the payload.

Related errors


AI-assisted analysis of projectdiscovery/subfinder@7a0b91f0fa (2026-09-06). Data as JSON: /api/errors/23327104d2d7cab5. Report an issue: GitHub.

Appendix: source

Thrown at pkg/subscraping/sources/alienvault/alienvault.go:73

			s.errors++
			session.DiscardHTTPResponse(resp)
			return
		}

		var response alienvaultResponse
		// Get the response body and decode
		err = json.NewDecoder(resp.Body).Decode(&response)
		if err != nil {
			results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
			s.errors++
			session.DiscardHTTPResponse(resp)
			return
		}
		session.DiscardHTTPResponse(resp)

		if response.Error != "" {
			results <- subscraping.Result{
				Source: s.Name(), Type: subscraping.Error, Error: fmt.Errorf("%s, %s", response.Detail, response.Error),
			}
			return
		}

		for _, record := range response.PassiveDNS {
			select {
			case <-ctx.Done():
				return
			case results <- subscraping.Result{Source: s.Name(), Type: subscraping.Subdomain, Value: record.Hostname}:
				s.results++
			}
		}
	}()

	return results
}

// Name returns the name of the source

View on GitHub (pinned to 7a0b91f0fa)