{"record":{"id":"e748e6b3aa2caa37","repo":"nats-io/nats-server","slug":"w-invalid-v1-format","errorCode":null,"errorMessage":"%w: invalid v1 format","messagePattern":"%w: invalid v1 format","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/client_proxyproto.go","lineNumber":176,"sourceCode":"\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\nfoundCRLF:\n\t// Get parts from the protocol\n\tparts := strings.Fields(string(line))\n\n\t// Validate format\n\tif len(parts) < 1 {\n\t\treturn nil, nil, fmt.Errorf(\"%w: invalid v1 format\", errProxyProtoInvalid)\n\t}\n\n\t// Handle UNKNOWN (health check, like v2 LOCAL)\n\tif parts[0] == proxyProtoV1Unknown {\n\t\treturn nil, remaining, nil\n\t}\n\n\t// Must have exactly 5 parts: protocol, src-ip, dst-ip, src-port, dst-port\n\tif len(parts) != 5 {\n\t\treturn nil, nil, fmt.Errorf(\"%w: invalid v1 format\", errProxyProtoInvalid)\n\t}\n\n\tprotocol := parts[0]\n\tsrcIP := net.ParseIP(parts[1])\n\tdstIP := net.ParseIP(parts[2])\n\n\tif srcIP == nil || dstIP == nil {\n\t\treturn nil, nil, fmt.Errorf(\"%w: invalid address\", errProxyProtoInvalid)","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/client_proxyproto.go#L158-L194","documentation":"After reading the v1 header line up to CRLF, the server splits it on whitespace and requires at least one token. An empty line (zero tokens) means the header contains only the 'PROXY ' prefix and nothing else, which cannot identify a protocol or address. This is a malformed-header rejection wrapping errProxyProtoInvalid.","triggerScenarios":"Client sends exactly 'PROXY \\r\\n' (or 'PROXY ' followed by only whitespace before CRLF) to a proxy-protocol-enabled listener; strings.Fields yields zero parts.","commonSituations":"Health-check script sending a bare 'PROXY ' probe; truncated header due to a proxy bug or packet fragmentation combined with premature CRLF; hand-rolled test client with a wrong format string.","solutions":["Fix the sender to emit a full v1 header like 'PROXY TCP4 <src> <dst> <sport> <dport>\\r\\n'","Use 'PROXY UNKNOWN\\r\\n' for health checks instead of a bare 'PROXY ' prefix","Check the proxy/load-balancer template for a truncated format string","Reproduce the raw bytes the sender writes and compare with the PROXY protocol v1 spec"],"exampleFix":"// before\nconn.Write([]byte(\"PROXY \\r\\n\"))\n// after\nconn.Write([]byte(\"PROXY TCP4 192.0.2.1 198.51.100.7 35646 4222\\r\\n\")) // or \"PROXY UNKNOWN\\r\\n\" for health checks","handlingStrategy":"validation","validationCode":"// Sender-side check before writing:\nheader := \"PROXY \" + payload // payload after prefix\nif len(strings.Fields(header)) < 2 && !strings.HasPrefix(payload, \"UNKNOWN\") {\n    return errors.New(\"PROXY v1 header needs protocol + 4 address fields, or UNKNOWN\")\n}","typeGuard":"func isCompleteV1Header(line string) bool {\n    return len(strings.Fields(strings.TrimSuffix(strings.TrimSuffix(line, \"\\n\"), \"\\r\"))) >= 1\n}","tryCatchPattern":"addr, _, err := readProxyProtoHeader(conn)\nif err != nil {\n    if errors.Is(err, errProxyProtoInvalid) {\n        log.Printf(\"empty/invalid PROXY v1 header: %v\", err)\n        conn.Close()\n        return nil\n    }\n    return err\n}","preventionTips":["Never send a bare 'PROXY ' line; use 'PROXY UNKNOWN\\r\\n' for health checks","Test your proxy's header template end-to-end before deployment","Use single spaces between fields per spec"],"tags":["proxy-protocol","network","nats","malformed-input"],"backgroundTag":"proxy-protocol-invalid-header","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}