projectdiscovery/nuclei · error
downloaded content is not valid JSON: %w
Error message
downloaded content is not valid JSON: %w
What it means
The OpenAPI spec URL returned HTTP 200 but the body is not parseable JSON. The downloader reads at most 10MB (io.LimitReader) and unmarshals into map[string]interface{}; any failure is wrapped with the underlying encoding/json error. Common causes: an HTML page (docs UI or login redirect served with 200), a YAML or plain-text body, a BOM, or a document truncated by the 10MB cap.
Source
Thrown at pkg/input/formats/openapi/downloader.go:66
}
defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("HTTP %d when downloading OpenAPI spec", resp.StatusCode)
}
bodyBytes, err := io.ReadAll(io.LimitReader(resp.Body, maxSpecSizeBytes))
if err != nil {
return "", errors.Wrap(err, "failed to read response body")
}
// Validate it's a valid JSON and has OpenAPI structure
var spec map[string]interface{}
if err := json.Unmarshal(bodyBytes, &spec); err != nil {
return "", fmt.Errorf("downloaded content is not valid JSON: %w", err)
}
// Check if it's an OpenAPI 3.0 spec
if openapi, exists := spec["openapi"]; exists {
if openapiStr, ok := openapi.(string); ok && strings.HasPrefix(openapiStr, "3.") {
// Valid OpenAPI 3.0 spec
} else {
return "", fmt.Errorf("not a valid OpenAPI 3.0 spec (found version: %v)", openapi)
}
} else {
return "", fmt.Errorf("not an OpenAPI spec (missing 'openapi' field)")
}
// Extract host from URL for server configuration
parsedURL, err := url.Parse(urlStr)
if err != nil {
return "", errors.Wrap(err, "failed to parse URL")
}View on GitHub (pinned to 265b3a3dec)
Solutions
- Fetch the URL with curl and inspect the raw body to see what is actually served
- If the body is YAML, switch to `-im swagger` (accepts .yaml/.yml) or convert the file to JSON and use `nuclei -l spec.json`
- Ensure the URL returns the raw spec document, not an HTML viewer or login page
- If the spec exceeds 10MB, split it or trim unused paths, then feed it as a local file
Example fix
# before: .json URL that actually serves YAML nuclei -im openapi -u https://host/spec.json # after: download locally and convert curl -s https://host/spec.json -o spec.yaml # convert YAML->JSON (e.g. yq -o=json '.' spec.yaml > spec.json) nuclei -l spec.json
Defensive patterns
Strategy: validation
Validate before calling
resp, err := http.Get(url)
if err != nil {
return err
}
body, _ := io.ReadAll(io.LimitReader(resp.Body, 10<<20))
if !json.Valid(body) {
return fmt.Errorf("body at %s is not JSON; inspect it before passing to nuclei", url)
} Type guard
func looksLikeOpenAPIJSON(body []byte) bool {
var spec map[string]json.RawMessage
if err := json.Unmarshal(body, &spec); err != nil {
return false
}
_, hasOpenAPI := spec["openapi"]
_, hasSwagger := spec["swagger"]
return hasOpenAPI || hasSwagger
} Try / catch
if err := downloader.Download(...); err != nil {
if strings.Contains(err.Error(), "not valid JSON") {
// body is HTML/YAML: fetch manually, convert, then use a local file
}
} Prevention
- Verify the spec URL serves raw JSON with curl before wiring it into automation
- Keep specs under 10MB or feed them as local files
- Convert YAML specs to JSON (yq -o=json) before using openapi mode
When it happens
Trigger: URL ends in .json but content negotiation returns HTML; SSO/login portals answering 200 with an HTML shell; a YAML body served under a .json name; specs larger than 10MB cut mid-document by the LimitReader; gzip/deflate double-encoding producing binary bytes.
Common situations: Docs sites where /openapi.json actually renders a viewer page; reverse proxies that inject scripts or cookies notices into responses; misconfigured static hosting guessing content type; very large machine-generated specs.
Related errors
- HTTP %d when downloading OpenAPI spec
- downloaded content is neither valid JSON nor YAML: %w
- failed to download %s spec from url %s: %w
- object can be a key:value or a string
- URL does not appear to be an OpenAPI JSON spec
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/289bb5259fa332ba.
Report an issue: GitHub.