projectdiscovery/nuclei · error

not a valid OpenAPI 3.0 spec (found version: %v)

Error message

not a valid OpenAPI 3.0 spec (found version: %v)

What it means

The downloaded JSON parsed fine and contains a top-level `openapi` field, but its value is not a string starting with "3." (e.g. "2.0", "4.0.0", or a non-string type such as a number). The downloader only supports OpenAPI 3.x documents, so any other version is rejected with the offending value in the message.

Source

Thrown at pkg/input/formats/openapi/downloader.go:74

	}

	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")
	}
	host := parsedURL.Host
	scheme := parsedURL.Scheme
	if scheme == "" {
		scheme = "https"
	}

	// Add servers section if missing or empty
	servers, exists := spec["servers"]

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. If the spec is Swagger 2.x, run with `-im swagger` instead
  2. If the spec is genuinely 3.x, ensure the field is a quoted string like "openapi": "3.0.3"
  3. Upgrade/convert the 2.0 spec to 3.x with a converter (e.g. swagger2openapi) if you must use openapi mode
  4. Check the printed 'found version' value to confirm what the server actually served

Example fix

# before (2.0 spec in openapi mode -> not a valid OpenAPI 3.0 spec)
nuclei -im openapi -u https://host/swagger.json

# after
nuclei -im swagger -u https://host/swagger.json
Defensive patterns

Strategy: validation

Validate before calling

var spec struct {
    OpenAPI any `json:"openapi"`
}
json.Unmarshal(body, &spec)
if v, ok := spec.OpenAPI.(string); !ok || !strings.HasPrefix(v, "3.") {
    return fmt.Errorf("spec is not OpenAPI 3.x; use swagger mode if it is 2.x")
}

Type guard

func isOpenAPI3(spec map[string]any) bool {
    v, ok := spec["openapi"].(string)
    return ok && strings.HasPrefix(v, "3.")
}

Try / catch

if strings.Contains(err.Error(), "not a valid OpenAPI 3.0 spec") {
    // switch to -im swagger for 2.x docs, or fix the version field to a "3.x.y" string
}

Prevention

When it happens

Trigger: Feeding a Swagger 2.0 document (swagger: "2.0" plus openapi-style hosting) to `-im openapi`; a spec generator emitting the version as a number (openapi: 3.0.1 is invalid JSON Schema typing); experimental 3.x-lookalike or 4.x specs.

Common situations: Old API gateways (API Gateway 2015-era exports, older Loopback/Swashbuckle) that only emit 2.0; hand-edited specs where the version string got mangled; mixing up the two input modes when a company has both v2 and v3 specs.

Related errors


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