projectdiscovery/nuclei · error
URL does not appear to be a Swagger spec (supported: %v)
Error message
URL does not appear to be a Swagger spec (supported: %v)
What it means
SwaggerDownloader.Download (pkg/input/formats/swagger/downloader.go) rejects URLs whose path does not end with one of the supported extensions reported by SupportedExtensions(): .json, .yaml, or .yml (case-sensitive strings.HasSuffix, checked before any request). Swagger mode must know the document format in advance, hence the extension gate.
Source
Thrown at pkg/input/formats/swagger/downloader.go:40
// NewDownloader creates a new Swagger downloader
func NewDownloader() formats.SpecDownloader {
return &SwaggerDownloader{}
}
// This function downloads a Swagger 2.0 spec from the given URL and saves it to tmpDir
func (d *SwaggerDownloader) Download(urlStr, tmpDir string, httpClient *retryablehttp.Client) (string, error) {
// Swagger can be JSON or YAML
supportedExts := d.SupportedExtensions()
isSupported := false
for _, ext := range supportedExts {
if strings.HasSuffix(urlStr, ext) {
isSupported = true
break
}
}
if !isSupported {
return "", fmt.Errorf("URL does not appear to be a Swagger spec (supported: %v)", supportedExts)
}
const maxSpecSizeBytes = 10 * 1024 * 1024 // 10MB
// Use provided httpClient or create a fallback
var client *http.Client
if httpClient != nil {
client = httpClient.HTTPClient
} else {
// Fallback to simple client if no httpClient provided
client = &http.Client{Timeout: 30 * time.Second}
}
resp, err := client.Get(urlStr)
if err != nil {
return "", errors.Wrap(err, "failed to download Swagger spec")
}
View on GitHub (pinned to 265b3a3dec)
Solutions
- Use a URL ending in .json, .yaml or .yml
- Strip query strings and fragments
- If the server cannot serve an extensioned URL, download manually (curl -o spec.yaml) and run `nuclei -l spec.yaml`
- Check the printed supported list in the error to confirm the exact suffixes accepted
Example fix
# before nuclei -im swagger -u https://api.example.com/v2/spec # after curl -s https://api.example.com/v2/spec -o spec.json nuclei -l spec.json -im swagger
Defensive patterns
Strategy: validation
Validate before calling
func isSwaggerDownloadable(u string) bool {
for _, ext := range []string{".json", ".yaml", ".yml"} {
if strings.HasSuffix(u, ext) {
return true
}
}
return false
} Try / catch
if _, err := downloader.Download(u, tmp, client); err != nil {
if strings.Contains(err.Error(), "does not appear to be a Swagger spec") {
// download manually and pass the local file: nuclei -l spec.json -im swagger
}
} Prevention
- Use extensioned spec URLs (.json/.yaml/.yml)
- Keep a local mirror of gateway-served specs for scanning
- Strip query strings from spec URLs
When it happens
Trigger: `nuclei -im swagger -u https://host/swagger` (no extension); URL with query string after the filename (swagger.json?access=x); uppercase .YAML; extension-less gateway routes like /v2/spec.
Common situations: Spec URLs behind API gateways or doc portals without file extensions; URLs with auth query parameters; copy-pasting the docs UI route instead of the raw spec.
Related errors
- URL does not appear to be an OpenAPI JSON spec
- not an OpenAPI spec (missing 'openapi' field)
- HTTP %d when downloading Swagger spec
- downloaded content is neither valid JSON nor YAML: %w
- not a valid Swagger 2.0 spec (found version: %v)
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/fdab74f06a68c402.
Report an issue: GitHub.