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
- Look up the numeric code in ThreatBook's API docs and address the stated cause in VerboseMsg.
- Verify the THREATBOOK_API_KEY is valid and has quota remaining.
- 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
- Map ThreatBook response codes to actions before running large scans.
- Track daily quota usage for your ThreatBook key.
- Confirm the key is provisioned for the subdomain endpoint.
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)