{"record":{"id":"e32a4ba280652f76","repo":"AlexxIT/go2rtc","slug":"malformed-response-s","errorCode":null,"errorMessage":"malformed response: %s","messagePattern":"malformed response: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/tcp/textproto.go","lineNumber":56,"sourceCode":"func (r *Response) Write(w io.Writer) (err error) {\n\t_, err = w.Write([]byte(r.String()))\n\treturn\n}\n\nfunc ReadResponse(r *bufio.Reader) (*Response, error) {\n\ttp := textproto.NewReader(r)\n\n\tline, err := tp.ReadLine()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif line == \"\" {\n\t\treturn nil, errors.New(\"empty response on RTSP request\")\n\t}\n\n\tss := strings.SplitN(line, \" \", 3)\n\tif len(ss) != 3 {\n\t\treturn nil, fmt.Errorf(\"malformed response: %s\", line)\n\t}\n\n\tres := &Response{\n\t\tStatus: ss[1] + \" \" + ss[2],\n\t\tProto:  ss[0],\n\t}\n\n\tres.StatusCode, err = strconv.Atoi(ss[1])\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tres.Header, err = tp.ReadMIMEHeader()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif val := res.Header.Get(\"Content-Length\"); val != \"\" {","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/tcp/textproto.go#L38-L74","documentation":"ReadResponse parses the first line of an RTSP response and requires exactly three space-separated fields: the protocol (e.g. RTSP/1.0), the status code, and the status text. If the line from the server does not split into exactly 3 parts, the library considers the response structurally malformed and refuses to build a Response. This guards against garbage bytes, partial reads, or non-RTSP replies on the socket.","triggerScenarios":"Calling ReadResponse (directly or via Dial/handshake/openTalkChannel) when the server's status line has fewer or more than 3 space-separated tokens, e.g. an empty-ish line, an HTML error page, or a line like 'RTSP/1.0 200' without a reason phrase.","commonSituations":"Connecting to a device that is not speaking RTSP on the given port; an HTTP proxy or captive portal returning non-RTSP output; custom cameras emitting non-conformant status lines; reading stale/partial buffered data after a previous failed request.","solutions":["Log the raw line shown in the error and confirm the peer is actually an RTSP server on that port (test with a raw RTSP OPTIONS request).","Verify the URL/port scheme — use rtsp:// and port 554 (or the camera's documented RTSP port), not the HTTP port.","Update camera firmware or use a vendor-specific transport (e.g. HTTP tunneling) if the device emits non-conformant status lines.","If the device omits the reason phrase, patch the parser or interpose a proxy that normalizes the status line to 3 fields."],"exampleFix":"// before\nres, err := conn.ReadResponse()\n// after\nline := readStatusLine(conn)\nif strings.Count(line, \" \") < 2 {\n\tlog.Fatalf(\"peer sent non-RTSP status line: %q\", line)\n}\nres, err := conn.ReadResponse()","handlingStrategy":"try-catch","validationCode":"// Peek the status line before trusting the response\nraw := peekStatusLine(conn)\nif len(strings.Fields(raw)) < 3 {\n\treturn fmt.Errorf(\"peer not speaking RTSP: %q\", raw)\n}","typeGuard":"func isRTSPStatusLine(line string) bool {\n\tparts := strings.SplitN(line, \" \", 3)\n\treturn len(parts) == 3 && strings.HasPrefix(parts[0], \"RTSP/\")\n}","tryCatchPattern":"res, err := conn.ReadResponse()\nif err != nil {\n\tif strings.Contains(err.Error(), \"malformed response\") {\n\t\treturn fmt.Errorf(\"non-RTSP peer on port: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Confirm the target port actually serves RTSP before dialing","Log raw status lines on parse failure for diagnostics","Pin to camera-documented RTSP ports and schemes","Normalize non-conformant devices with a proxy if needed"],"tags":["rtsp","parsing","protocol","network"],"backgroundTag":"unexpected-response-shape","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}