{"record":{"id":"37a0a0289655e350","repo":"projectdiscovery/nuclei","slug":"failed-to-download-s-spec-from-url-s-w","errorCode":null,"errorMessage":"failed to download %s spec from url %s: %w","messagePattern":"failed to download (.+?) spec from url (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/input/provider/interface.go","lineNumber":150,"sourceCode":"\t\t\t\tdialers := protocolstate.GetDialersWithId(opts.Options.ExecutionId)\n\t\t\t\tif dialers != nil {\n\t\t\t\t\thttpClient = dialers.DefaultHTTPClient\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tswitch strings.ToLower(opts.Options.InputFileMode) {\n\t\t\tcase \"openapi\":\n\t\t\t\tdownloader = openapi.NewDownloader()\n\t\t\t\ttempFile, err = downloader.Download(target, opts.TempDir, httpClient)\n\t\t\tcase \"swagger\":\n\t\t\t\tdownloader = swagger.NewDownloader()\n\t\t\t\ttempFile, err = downloader.Download(target, opts.TempDir, httpClient)\n\t\t\tdefault:\n\t\t\t\treturn nil, fmt.Errorf(\"unsupported input mode: %s\", opts.Options.InputFileMode)\n\t\t\t}\n\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to download %s spec from url %s: %w\", opts.Options.InputFileMode, target, err)\n\t\t\t}\n\n\t\t\topts.Options.TargetsFilePath = tempFile\n\t\t}\n\t}\n\n\treturn http.NewHttpInputProvider(&http.HttpMultiFormatOptions{\n\t\tInputFile: opts.Options.TargetsFilePath,\n\t\tInputMode: opts.Options.InputFileMode,\n\t\tOptions: formats.InputFormatOptions{\n\t\t\tVariables:            generators.MergeMaps(extraVars, opts.Options.Vars.AsMap()),\n\t\t\tSkipFormatValidation: opts.Options.SkipFormatValidation,\n\t\t\tRequiredOnly:         opts.Options.FormatUseRequiredOnly,\n\t\t\tVarsTextTemplating:   opts.Options.VarsTextTemplating,\n\t\t\tVarsFilePaths:        opts.Options.VarsFilePaths,\n\t\t},\n\t})\n}","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/input/provider/interface.go#L132-L168","documentation":"Nuclei is trying to turn a URL target into an OpenAPI/Swagger input list. When exactly one -target starting with http(s):// is combined with -im openapi or -im swagger, provider.New() calls the corresponding formats downloader to fetch the spec into a temp file. This error wraps any failure of that Download(): network error, non-200 response, spec parse failure, or temp-file write failure.","triggerScenarios":"Running with a single http(s) URL target and -im openapi|swagger where downloader.Download(target, opts.TempDir, httpClient) fails: spec URL unreachable, returns 401/403/404/HTML error page, is not valid OpenAPI/Swagger JSON-YAML, or TempDir is not writable.","commonSituations":"Spec endpoint behind authentication; corporate proxy or TLS interception mangling the fetch; typo'd spec URL; mode mismatch (Swagger 2.0 spec fed with -im openapi or vice versa); -temp-dir pointing to a read-only location; the ExecutionId-scoped dialer (protocolstate) restricting network access for SDK runs.","solutions":["Fetch the URL out-of-band (curl -sSL -o spec.json <url>) and confirm it returns 200 with a valid spec body; if auth is required, download manually and pass the file via -l instead of a URL target","Make -im match the spec version: openapi for OpenAPI 3.x documents, swagger for Swagger 2.0","Verify the temp dir (-temp-dir) exists and is writable","For SDK runs, ensure the protocolstate dialer/network policy for that ExecutionId permits the spec host"],"exampleFix":"# before\nnuclei -t probes -target https://internal/api-spec.json -im openapi\n\n# after\ncurl -sSL -H \"Authorization: Bearer $TOKEN\" -o spec.json https://internal/api-spec.json && nuclei -t probes -l spec.json -im openapi","handlingStrategy":"validation","validationCode":"resp, err := http.Get(specURL)\nif err != nil {\n    return fmt.Errorf(\"preflight failed: %w\", err)\n}\ndefer resp.Body.Close()\nif resp.StatusCode != 200 {\n    return fmt.Errorf(\"spec URL returned %d — download it manually and pass via -l\", resp.StatusCode)\n}\nbody, _ := io.ReadAll(io.LimitReader(resp.Body, 1<<20))\nif !json.Valid(body) {\n    return fmt.Errorf(\"URL did not return JSON — likely an auth/error page\")\n}","typeGuard":null,"tryCatchPattern":"Wrap provider creation (or nuclei run setup) and on this error fall back to feeding the spec as a local file via TargetsFilePath, e.g. download with the needed auth headers yourself, then hand the file to the input provider.","preventionTips":["Pre-fetch the spec with the same proxy/auth the scanner will use before starting a run","Match -im (openapi vs swagger) to the actual spec version","Keep the temp dir (-temp-dir) writable and on a volume with space","For SDK runs, allowlist the spec host in protocolstate's network policy for that ExecutionId"],"tags":["network","input","openapi","swagger","download"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}