{"record":{"id":"4c298d24a6fb9997","repo":"nats-io/nats-server","slug":"failed-to-read-v1-line-w","errorCode":null,"errorMessage":"failed to read v1 line: %w","messagePattern":"failed to read v1 line: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/client_proxyproto.go","lineNumber":151,"sourceCode":"\n// readProxyProtoV1Header parses PROXY protocol v1 text format.\n// Expects the \"PROXY \" prefix (6 bytes) to have already been consumed.\n// Returns any bytes that were read past the trailing CRLF so the caller can\n// replay them into the next protocol layer.\nfunc readProxyProtoV1Header(conn net.Conn) (*proxyProtoAddr, []byte, error) {\n\t// Read rest of line (max 107 bytes total, already read 6)\n\tmaxRemaining := proxyProtoV1MaxLineLen - 6\n\n\t// Read up to maxRemaining bytes at once (more efficient than byte-by-byte)\n\tbuf := make([]byte, maxRemaining)\n\tvar line []byte\n\tvar remaining []byte\n\n\tfor len(line) < maxRemaining {\n\t\t// Read available data\n\t\tn, err := conn.Read(buf[len(line):])\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"failed to read v1 line: %w\", err)\n\t\t}\n\n\t\tline = buf[:len(line)+n]\n\n\t\t// Look for CRLF in what we've read so far\n\t\tfor i := 0; i < len(line)-1; i++ {\n\t\t\tif line[i] == '\\r' && line[i+1] == '\\n' {\n\t\t\t\t// Found CRLF - keep any over-read bytes for the client parser.\n\t\t\t\tremaining = append(remaining, line[i+2:]...)\n\t\t\t\tline = line[:i]\n\t\t\t\tgoto foundCRLF\n\t\t\t}\n\t\t}\n\t}\n\n\t// Exceeded max length without finding CRLF\n\treturn nil, nil, fmt.Errorf(\"%w: v1 line too long\", errProxyProtoInvalid)\n","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/client_proxyproto.go#L133-L169","documentation":"After detecting PROXY protocol v1, the server reads the rest of the header line up to CRLF; conn.Read failed mid-read (timeout, reset, EOF), so the v1 header could not be completed and the wrapped I/O error is returned.","triggerScenarios":"A PROXY v1 sender writes fewer than 6 bytes then stalls, is killed, or the connection is reset before the full `PROXY ... CRLF` line arrives; also triggered when the line exceeds maxRemaining without CRLF causing continued reads to fail.","commonSituations":"Misconfigured load balancer sending a truncated PROXY v1 line, flaky network between proxy and NATS server, proxy crashed mid-handshake, MTU/buffer issues truncating the header.","solutions":["Fix the upstream proxy to send the complete single-line PROXY v1 header terminated by CRLF","Check proxy health/stability and network path (resets, timeouts) between proxy and server","Verify the proxy version supports PROXY protocol v1 and its header fits on one line under maxRemaining","Reproduce with packet capture on the server port to see the truncated header bytes"],"exampleFix":"// before (truncated header)\nPROXY TCP4 10.0.0.1\n// after (complete v1 line with CRLF)\nPROXY TCP4 10.0.0.1 10.0.0.2 50000 4222\\r\\n","handlingStrategy":"fallback","validationCode":"// sender side: ensure full line + CRLF is written before flushing\nheader := fmt.Sprintf(\"PROXY TCP4 %s %s %d %d\\r\\n\", srcIP, dstIP, srcPort, dstPort)\nif n, err := conn.Write([]byte(header)); err != nil || n != len(header) {\n    return fmt.Errorf(\"short proxy header write: %d/%d\", n, len(header))\n}","typeGuard":null,"tryCatchPattern":"header, err := readProxyProtoHeader(conn)\nif err != nil {\n    // inspect wrapped cause; retry or fall back to direct connection\n    return fmt.Errorf(\"proxy header failed: %w\", err)\n}","preventionTips":["Write the entire PROXY v1 line in a single buffered write ending with CRLF","Keep the proxy-server network path stable; monitor for resets","Ensure the header line length stays under the server's maxRemaining limit","Test load balancer PROXY protocol configuration with a packet capture"],"tags":["network","proxy-protocol","tcp"],"backgroundTag":"proxy-protocol-header-read-failed","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}