projectdiscovery/nuclei · error

downloaded content is neither valid JSON nor YAML: %w

Error message

downloaded content is neither valid JSON nor YAML: %w

What it means

The Swagger spec URL returned HTTP 200 but the body parses as neither JSON nor YAML: the downloader tries encoding/json first, then gopkg.in/yaml.v3, and wraps the YAML parser error. Bodies like HTML pages, plain text, or binary content fail both parses; documents larger than the 10MB LimitReader cap can be truncated into invalid syntax.

Source

Thrown at pkg/input/formats/swagger/downloader.go:80

	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("HTTP %d when downloading Swagger spec", resp.StatusCode)
	}

	bodyBytes, err := io.ReadAll(io.LimitReader(resp.Body, maxSpecSizeBytes))
	if err != nil {
		return "", errors.Wrap(err, "failed to read response body")
	}

	// Determine format and parse
	var spec map[string]interface{}
	var isYAML bool

	// Try JSON first
	if err := json.Unmarshal(bodyBytes, &spec); err != nil {
		// Then try YAML
		if err := yaml.Unmarshal(bodyBytes, &spec); err != nil {
			return "", fmt.Errorf("downloaded content is neither valid JSON nor YAML: %w", err)
		}
		isYAML = true
	}

	// Validate it's a Swagger 2.0 spec
	if swagger, exists := spec["swagger"]; exists {
		if swaggerStr, ok := swagger.(string); ok && strings.HasPrefix(swaggerStr, "2.") {
			// Valid Swagger 2.0 spec
		} else {
			return "", fmt.Errorf("not a valid Swagger 2.0 spec (found version: %v)", swagger)
		}
	} else {
		return "", fmt.Errorf("not a Swagger spec (missing 'swagger' field)")
	}

	// Extract host from URL for host configuration
	parsedURL, err := url.Parse(urlStr)
	if err != nil {

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. curl the URL and inspect the first lines of the raw body
  2. If it is HTML, find the real spec link inside the page (look for spec-url / swagger config) and use that
  3. If truncated by size, split or trim the spec and feed it as a local file
  4. Ensure no proxy is injecting content (try --noproxy or a different network)

Example fix

# before (URL serves the docs UI HTML)
nuclei -im swagger -u https://host/docs

# after
curl -s https://host/api-docs/swagger.yaml -o spec.yaml
nuclei -l spec.yaml -im swagger
Defensive patterns

Strategy: validation

Validate before calling

resp, _ := http.Get(url)
body, _ := io.ReadAll(io.LimitReader(resp.Body, 10<<20))
if !json.Valid(body) {
    var y any
    if err := yaml.Unmarshal(body, &y); err != nil {
        return fmt.Errorf("body is neither JSON nor YAML (likely HTML or truncated)")
    }
}

Type guard

func isJSONorYAML(body []byte) bool {
    if json.Valid(body) {
        return true
    }
    var y any
    return yaml.Unmarshal(body, &y) == nil
}

Try / catch

if strings.Contains(err.Error(), "neither valid JSON nor YAML") {
    // inspect the raw body: usually a login/HTML page; find the real spec link
}

Prevention

When it happens

Trigger: Docs UI HTML returned at the spec URL; SSO/login pages answering 200; CDN error pages or CAPTCHA challenges; plain-text error messages; >10MB specs cut mid-document.

Common situations: Portals that serve the viewer app on every route; response-rewriting proxies; huge auto-generated specs exceeding the size cap.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/32c19cea4d21df29. Report an issue: GitHub.