{"record":{"id":"c43d9d2b259a26a8","repo":"valyala/fasthttp","slug":"fasthttp-unexpected-char-at-the-end-of-status-cod","errorCode":null,"errorMessage":"fasthttp: unexpected char at the end of status code","messagePattern":"fasthttp: unexpected char at the end of status code","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"header.go","lineNumber":473,"sourceCode":"// The following trailers are forbidden:\n// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),\n// 2. routing (e.g., Host),\n// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),\n// 4. authentication (e.g., see [RFC7235] and [RFC6265]),\n// 5. response control data (e.g., see Section 7.1 of [RFC7231]),\n// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)\n//\n// Return ErrBadTrailer if contain any forbidden trailers.\nfunc (h *header) AddTrailer(trailer string) error {\n\treturn h.AddTrailerBytes(s2b(trailer))\n}\n\nvar (\n\tErrBadTrailer                    = errors.New(\"fasthttp: contain forbidden trailer\")\n\tErrReadingResponseHeaders        = errors.New(\"fasthttp: error when reading response headers\")\n\tErrReadingResponseTrailer        = errors.New(\"fasthttp: error when reading response trailer\")\n\tErrResponseFirstLineMissingSpace = errors.New(\"fasthttp: cannot find whitespace in the first line of response\")\n\tErrUnexpectedStatusCodeChar      = errors.New(\"fasthttp: unexpected char at the end of status code\")\n\tErrMissingRequestMethod          = errors.New(\"fasthttp: cannot find http request method\")\n\tErrUnsupportedRequestMethod      = errors.New(\"fasthttp: unsupported http request method\")\n\tErrExtraWhitespaceInRequestLine  = errors.New(\"fasthttp: extra whitespace in request line\")\n\tErrEmptyRequestURI               = errors.New(\"fasthttp: requesturi cannot be empty\")\n\tErrDuplicateContentLength        = errors.New(\"fasthttp: duplicate content-length header\")\n\tErrUnsupportedTransferEncoding   = errors.New(\"fasthttp: unsupported transfer-encoding\")\n\tErrNonNumericChars               = errors.New(\"fasthttp: non-numeric chars found\")\n\tErrNeedMore                      = errors.New(\"fasthttp: need more data: cannot find trailing lf\")\n\tErrSmallReadBuffer               = errors.New(\"fasthttp: small read buffer. increase readbuffersize\")\n)\n\n// AddTrailerBytes add Trailer header value for chunked response\n// to indicate which headers will be sent after the body.\n//\n// Use Set to set the trailer header later.\n//\n// Trailers are only supported with chunked transfer.\n// Trailers allow the sender to include additional headers at the end of chunked messages.","sourceCodeStart":455,"sourceCodeEnd":491,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/header.go#L455-L491","documentation":"While parsing a response status line, fasthttp reads the 3-digit status code and expects it to be followed by a space, CR/LF, or end of line. If an unexpected character appears where the status code should end, ErrUnexpectedStatusCodeChar is returned. It indicates the peer sent a syntactically invalid status line.","triggerScenarios":"Response.Read / Client.Do / HostClient.Do on a response whose first line is like 'HTTP/1.1 20x OK' or 'HTTP/1.1 1234abc' — any non-digit/non-separator char after the status digits (see fasthttputil/ParseUint usage in parseFirstLine).","commonSituations":"Talking to a misbehaving or nonconformant server/proxy, an adversarial or fuzzed peer, or a port returning proprietary protocol data instead of HTTP. Also common when TLS is missing so raw handshake bytes are parsed as HTTP.","solutions":["Log the raw first line (wrap the conn or use curl -v against the same URL) to see what the peer actually returns.","Fix the upstream server/proxy to emit RFC-compliant status lines like 'HTTP/1.1 200 OK'.","Ensure the https:// scheme and TLSClientConfig are set for TLS servers so ciphertext is not parsed as plain HTTP.","Retry against a healthy endpoint; fasthttp closes the connection after this parse error so the pooled conn is discarded."],"exampleFix":"// before\nreq.SetRequestURI(\"http://svc.internal:8443/x\") // TLS server, plain HTTP request\n// after\nreq.SetRequestURI(\"https://svc.internal:8443/x\")\nclient.TLSConfig = &tls.Config{ InsecureSkipVerify: true } // trust setup as needed","handlingStrategy":"type-guard","validationCode":"// Probe the raw status line once at startup:\n// curl -sv URL | head -1 must match '^HTTP/1\\.[01] [0-9]{3} '\n","typeGuard":"func isBadStatusLine(err error) bool {\n    return err == fasthttp.ErrUnexpectedStatusCodeChar\n}","tryCatchPattern":"err := client.Do(req, resp)\nif err == fasthttp.ErrUnexpectedStatusCodeChar {\n    client.CloseIdleConnections() // discard possibly-corrupted pooled conns\n    return retryable(fmt.Errorf(\"malformed status line: %w\", err))\n}","preventionTips":["Use TLS (https scheme) with TLS servers so ciphertext is never parsed as HTTP.","Pin and test upstream server versions in CI — nonconformant proxies emit bad status lines.","Log first bytes of failed responses via a wrapped dialer for diagnosis.","Treat bursts of this error as a compromised/misbehaving middlebox signal."],"tags":["network","http","fasthttp","response-parsing"],"backgroundTag":"malformed-http-response","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}