{"record":{"id":"a1560dfa8f106540","repo":"projectdiscovery/subfinder","slug":"s-a1560d","errorCode":null,"errorMessage":"%s","messagePattern":"%s","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/subscraping/sources/fofa/fofa.go","lineNumber":81,"sourceCode":"\t\t\tresults <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}\n\t\t\ts.errors++\n\t\t\tsession.DiscardHTTPResponse(resp)\n\t\t\treturn\n\t\t}\n\n\t\tvar response fofaResponse\n\t\terr = jsoniter.NewDecoder(resp.Body).Decode(&response)\n\t\tif err != nil {\n\t\t\tresults <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: err}\n\t\t\ts.errors++\n\t\t\tsession.DiscardHTTPResponse(resp)\n\t\t\treturn\n\t\t}\n\t\tsession.DiscardHTTPResponse(resp)\n\n\t\tif response.Error {\n\t\t\tresults <- subscraping.Result{\n\t\t\t\tSource: s.Name(), Type: subscraping.Error, Error: fmt.Errorf(\"%s\", response.ErrMsg),\n\t\t\t}\n\t\t\ts.errors++\n\t\t\treturn\n\t\t}\n\n\t\tif response.Size > 0 {\n\t\t\tfor _, subdomain := range response.Results {\n\t\t\t\tselect {\n\t\t\t\tcase <-ctx.Done():\n\t\t\t\t\treturn\n\t\t\t\tdefault:\n\t\t\t\t}\n\t\t\t\tif strings.HasPrefix(strings.ToLower(subdomain), \"http://\") || strings.HasPrefix(strings.ToLower(subdomain), \"https://\") {\n\t\t\t\t\tsubdomain = subdomain[strings.Index(subdomain, \"//\")+2:]\n\t\t\t\t}\n\t\t\t\tre := regexp.MustCompile(`:\\d+$`)\n\t\t\t\tif re.MatchString(subdomain) {\n\t\t\t\t\tsubdomain = re.ReplaceAllString(subdomain, \"\")","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/projectdiscovery/subfinder/blob/7a0b91f0fac01b62c65328bd771a3560ae611d6a/pkg/subscraping/sources/fofa/fofa.go#L63-L99","documentation":"The FOFA source in subscraping received an HTTP 200 response whose JSON body flagged an application-level error (response.Error == true). The library surfaces the API's own ErrMsg field verbatim as a Go error and pushes it on the results channel, then stops enumeration for this source. It means the FOFA API rejected the query even though the HTTP request itself succeeded.","triggerScenarios":"Any FOFA API call where the decoded response has error=true, with response.ErrMsg carrying the API's message — e.g. invalid API email/key pair, malformed or non-Base64 query string, query violating FOFA syntax, or account quota/privilege limits (FOFA 'personal' plan API restrictions).","commonSituations":"Expired or wrong FOFA API credentials (FOFA_EMAIL/FOFA_KEY), passing a raw query that is not Base64-encoded, using query syntax not allowed on the user's FOFA tier, or hitting the monthly API quota (FOFA returns 'VIP query limit' style messages).","solutions":["Verify FOFA_EMAIL and FOFA_KEY are set correctly and belong to an account with API access","Base64-encode the query string exactly as FOFA requires and test the same request with curl","Check your FOFA account quota and plan level (some query types need paid VIP)","Read the ErrMsg returned in this error — it contains FOFA's own explanation of the rejection"],"exampleFix":"// before\nresults <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: fmt.Errorf(\"%s\", response.ErrMsg)}\n// after\nif response.ErrMsg == \"\" {\n    response.ErrMsg = \"unknown FOFA API error\"\n}\nresults <- subscraping.Result{Source: s.Name(), Type: subscraping.Error, Error: fmt.Errorf(\"fofa api error: %s\", response.ErrMsg)}","handlingStrategy":"validation","validationCode":"email := os.Getenv(\"FOFA_EMAIL\")\nkey := os.Getenv(\"FOFA_KEY\")\nif email == \"\" || key == \"\" {\n    return fmt.Errorf(\"FOFA_EMAIL and FOFA_KEY must be set with a valid FOFA API account\")\n}\nif _, err := base64.StdEncoding.DecodeString(query); err != nil {\n    return fmt.Errorf(\"FOFA query must be Base64-encoded: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"for res := range src.Fetch(ctx, domain) {\n    if res.Type == subscraping.Error {\n        if strings.Contains(res.Error.Error(), \"account\") || strings.Contains(res.Error.Error(), \"VIP\") {\n            // credentials/quota problem — skip FOFA, do not retry\n            continue\n        }\n        log.Printf(\"fofa: %v\", res.Error)\n    }\n}","preventionTips":["Validate FOFA credentials once at startup with a cheap API call before bulk runs","Always Base64-encode queries exactly as FOFA's API docs specify","Track FOFA monthly quota and stop before exhaustion","Surface response.ErrMsg in your own logs — it names the exact cause"],"tags":["network","api","http","subdomain-enumeration"],"backgroundTag":"api-error-response","analyzedSha":"7a0b91f0fac01b62c65328bd771a3560ae611d6a","analyzedAt":"2026-09-06T23:52:02.109Z","contentChangedAt":"2026-09-06T23:52:02.109Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}