{"record":{"id":"06ea171c7fec6b72","repo":"projectdiscovery/nuclei","slug":"not-a-valid-swagger-2-0-spec-found-version-v","errorCode":null,"errorMessage":"not a valid Swagger 2.0 spec (found version: %v)","messagePattern":"not a valid Swagger 2\\.0 spec \\(found version: (.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/input/formats/swagger/downloader.go","lineNumber":90,"sourceCode":"\t// Determine format and parse\n\tvar spec map[string]interface{}\n\tvar isYAML bool\n\n\t// Try JSON first\n\tif err := json.Unmarshal(bodyBytes, &spec); err != nil {\n\t\t// Then try YAML\n\t\tif err := yaml.Unmarshal(bodyBytes, &spec); err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"downloaded content is neither valid JSON nor YAML: %w\", err)\n\t\t}\n\t\tisYAML = true\n\t}\n\n\t// Validate it's a Swagger 2.0 spec\n\tif swagger, exists := spec[\"swagger\"]; exists {\n\t\tif swaggerStr, ok := swagger.(string); ok && strings.HasPrefix(swaggerStr, \"2.\") {\n\t\t\t// Valid Swagger 2.0 spec\n\t\t} else {\n\t\t\treturn \"\", fmt.Errorf(\"not a valid Swagger 2.0 spec (found version: %v)\", swagger)\n\t\t}\n\t} else {\n\t\treturn \"\", fmt.Errorf(\"not a Swagger spec (missing 'swagger' field)\")\n\t}\n\n\t// Extract host from URL for host configuration\n\tparsedURL, err := url.Parse(urlStr)\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to parse URL\")\n\t}\n\n\thost := parsedURL.Host\n\tscheme := parsedURL.Scheme\n\tif scheme == \"\" {\n\t\tscheme = \"https\"\n\t}\n\n\t// Add host if missing","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/input/formats/swagger/downloader.go#L72-L108","documentation":"The downloaded document parsed as JSON/YAML and has a top-level `swagger` field, but its value does not start with \"2.\" (the value is printed in the message). SwaggerDownloader only supports Swagger 2.0 documents; an OpenAPI 3.x value (\"3.0.1\"), a non-string type, or a bogus version is rejected.","triggerScenarios":"Feeding an OpenAPI 3 spec (which usually uses `openapi:` but some tools duplicate it as swagger: \"3...\") to `-im swagger`; generators emitting swagger: \"2\" without minor version; mislabeled internal specs.","commonSituations":"Guessing the input mode when a company has mixed v2/v3 specs; conversion tools that leave stale swagger keys; hand-edited version fields.","solutions":["If the document is OpenAPI 3.x, use `-im openapi` instead (JSON, .json URL)","If the version string is malformed (e.g. \"2\"), fix it to \"2.0\" in the spec","Convert 3.x down to 2.0 only if you must stay in swagger mode","Read the 'found version' in the message to see what the server actually served"],"exampleFix":"# before (3.x doc in swagger mode)\nnuclei -im swagger -u https://host/openapi.json\n\n# after\nnuclei -im openapi -u https://host/openapi.json","handlingStrategy":"validation","validationCode":"var spec map[string]any\njson.Unmarshal(body, &spec) // or yaml\nif v, ok := spec[\"swagger\"].(string); !ok || !strings.HasPrefix(v, \"2.\") {\n    if ov, _ := spec[\"openapi\"].(string); strings.HasPrefix(ov, \"3.\") {\n        return fmt.Errorf(\"use -im openapi for this document\")\n    }\n}","typeGuard":"func isSwagger2(spec map[string]any) bool {\n    v, ok := spec[\"swagger\"].(string)\n    return ok && strings.HasPrefix(v, \"2.\")\n}","tryCatchPattern":"if strings.Contains(err.Error(), \"not a valid Swagger 2.0 spec\") {\n    // switch input mode to openapi for 3.x documents, or fix a malformed version string\n}","preventionTips":["Read the version marker before choosing the input mode","Keep one canonical mode per service in your scan config","Fix specs whose version field is not a proper \"2.x\" string"],"tags":["swagger","version","spec-validation","input-mode"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}