{"record":{"id":"6685150495b27527","repo":"projectdiscovery/nuclei","slug":"invalid-method-line-s","errorCode":null,"errorMessage":"invalid method line: %s","messagePattern":"invalid method line: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/input/types/http.go","lineNumber":238,"sourceCode":"\t}\n}\n\n// ParseRawRequest parses a raw request from a string\n// and returns the request and response object\n// Note: it currently does not parse response and is meant to be added manually since its a optional field\nfunc ParseRawRequest(raw string) (rr *RequestResponse, err error) {\n\tprotoReader := textproto.NewReader(bufio.NewReader(strings.NewReader(raw)))\n\tmethodLine, err := protoReader.ReadLine()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read method line: %s\", err)\n\t}\n\trr = &RequestResponse{\n\t\tRequest: &HttpRequest{},\n\t}\n\t/// must contain at least 3 parts\n\tparts := strings.Split(methodLine, \" \")\n\tif len(parts) < 3 {\n\t\treturn nil, fmt.Errorf(\"invalid method line: %s\", methodLine)\n\t}\n\tmethod := parts[0]\n\trr.Request.Method = method\n\n\t// the request target is normally an origin-form path, but proxy captures and\n\t// .http files use the absolute form, which already carries the authority\n\tvar urlx *urlutil.URL\n\ttarget := parts[1]\n\tif stringsutil.HasPrefixAnyI(target, urlutil.HTTP+urlutil.SchemeSeparator, urlutil.HTTPS+urlutil.SchemeSeparator) {\n\t\t// urlutil.ParseAbsoluteURL only accepts lowercase schemes; preserve the\n\t\t// remainder of the request target unchanged.\n\t\tif scheme, rest, ok := strings.Cut(target, urlutil.SchemeSeparator); ok {\n\t\t\ttarget = strings.ToLower(scheme) + urlutil.SchemeSeparator + rest\n\t\t}\n\t\turlx, err = urlutil.ParseAbsoluteURL(target, true)\n\t} else {\n\t\turlx, err = urlutil.ParseRawRelativePath(target, true)\n\t}","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/input/types/http.go#L220-L256","documentation":"The first line of a raw request split on single spaces yielded fewer than 3 parts, so method, target, or HTTP version is missing. Nuclei requires 'METHOD SP TARGET SP VERSION' exactly; tabs or multiple spaces still count as separators only if they are literal single spaces in the split sense.","triggerScenarios":"Lines like 'GET /' (no version), 'GET' alone, 'GET/' merged, or a first line that is actually prose or a comment pasted above the request.","commonSituations":"Editing raw requests in templates and deleting the version; proxy exports that drop HTTP/1.1; using commas or tabs instead of spaces; HTTP/2 pseudo-headers (':method: GET') pasted as the first line.","solutions":["Rewrite the first line as three space-separated parts, e.g. 'POST /login HTTP/1.1'","Use plain ASCII spaces, not tabs, between the three parts","Strip comment lines or editorial text above the request"],"exampleFix":"# before\nraw: |\n  GET /\n  Host: example.com\n\n# after\nraw: |\n  GET / HTTP/1.1\n  Host: example.com","handlingStrategy":"validation","validationCode":"first := strings.SplitN(raw, \"\\n\", 2)[0]\nparts := strings.Split(first, \" \")\nif len(parts) < 3 || parts[0] == \"\" || parts[1] == \"\" {\n    return fmt.Errorf(\"method line malformed: %q\", first)\n}","typeGuard":null,"tryCatchPattern":"Catch and repair: if the first line has 2 parts, append ' HTTP/1.1' and re-parse once; otherwise drop the entry.","preventionTips":["Standardize on 'METHOD SP TARGET SP HTTP/1.1'","Never paste HTTP/2 pseudo-header lines into raw requests","Validate raw requests in template CI with nuclei -validate"],"tags":["input","raw-http","parsing","template"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}