projectdiscovery/subfinder · error

code

Error message

code %d, %s

What it means

The threatbook source raises this when the ThreatBook API response carries a non-zero ResponseCode. ThreatBook encodes request failures (auth, quota, bad params) in this code with a human-readable VerboseMsg, which the library formats as "code %d, %s".

Solutions

  1. Look up the numeric code in ThreatBook's API docs and address the stated cause in VerboseMsg.
  2. Verify the THREATBOOK_API_KEY is valid and has quota remaining.
  3. Retry after quota reset or upgrade the ThreatBook plan if code indicates limit exhaustion.
Defensive patterns

Strategy: try-catch

Validate before calling

if os.Getenv("THREATBOOK_API_KEY") == "" { return errors.New("THREATBOOK_API_KEY not set") }

Try / catch

for r := range results {
  if r.Type == subscraping.Error {
    var code int
    if n, _ := fmt.Sscanf(r.Error.Error(), "code %d", &code); n == 1 {
      switch code {
      case quotaCode:
        // wait for reset or upgrade plan
      case authCode:
        // fix API key
      }
    }
  }
}

Prevention

When it happens

Trigger: Any ThreatBook API call that returns JSON with response_code != 0 — invalid/expired API key, daily quota exhausted, or an unsupported/invalid query parameter.

Common situations: Free-tier ThreatBook key out of daily quota; key not provisioned for the subdomain endpoint; deprecated API version producing param errors.

Related errors


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

Appendix: source

Thrown at pkg/subscraping/sources/threatbook/threatbook.go:78

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

		var response threatBookResponse
		err = jsoniter.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.ResponseCode != 0 {
			results <- subscraping.Result{
				Source: s.Name(), Type: subscraping.Error,
				Error: fmt.Errorf("code %d, %s", response.ResponseCode, response.VerboseMsg),
			}
			s.errors++
			return
		}

		total, err := strconv.ParseInt(response.Data.SubDomains.Total, 10, 64)
		if err != nil {
			results <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}
			s.errors++
			return
		}

		if total > 0 {
			for _, subdomain := range response.Data.SubDomains.Data {
				select {
				case <-ctx.Done():
					return
				case results <- subscraping.Result{Source: s.Name(), Type: subscraping.Subdomain, Value: subdomain}:

View on GitHub (pinned to 7a0b91f0fa)