{"record":{"id":"139dc920f9395237","repo":"valyala/fasthttp","slug":"empty-ip-address-string","errorCode":null,"errorMessage":"empty ip address string","messagePattern":"empty ip address string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"bytesconv.go","lineNumber":71,"sourceCode":"}\n\n// AppendIPv4 appends string representation of the given ip v4 to dst\n// and returns the extended dst.\nfunc AppendIPv4(dst []byte, ip net.IP) []byte {\n\tip = ip.To4()\n\tif len(ip) != net.IPv4len {\n\t\treturn append(dst, \"non-v4 ip passed to AppendIPv4\"...)\n\t}\n\n\tdst = AppendUint(dst, int(ip[0]))\n\tfor i := 1; i < 4; i++ {\n\t\tdst = append(dst, '.')\n\t\tdst = AppendUint(dst, int(ip[i]))\n\t}\n\treturn dst\n}\n\nvar errEmptyIPStr = errors.New(\"empty ip address string\")\n\nvar httpDateGMT = time.FixedZone(\"GMT\", 0)\n\n// ParseIPv4 parses ip address from ipStr into dst and returns the extended dst.\nfunc ParseIPv4(dst net.IP, ipStr []byte) (net.IP, error) {\n\tif len(ipStr) == 0 {\n\t\treturn dst, errEmptyIPStr\n\t}\n\tif len(dst) < net.IPv4len || len(dst) > net.IPv4len {\n\t\tdst = make([]byte, net.IPv4len)\n\t}\n\tcopy(dst, net.IPv4zero)\n\tdst = dst.To4() // dst is always non-nil here\n\n\tb := ipStr\n\tfor i := range 3 {\n\t\tn := bytes.IndexByte(b, '.')\n\t\tif uint(n) >= uint(len(b)) {","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/valyala/fasthttp/blob/c96f600972c6f4a7a30d664257b340ebe9d60124/bytesconv.go#L53-L89","documentation":"errEmptyIPStr is returned by ParseIPv4 when the input ipStr byte slice has zero length. ParseIPv4 cannot parse an IP from nothing, so it fails fast instead of producing a zero IP. It is an internal sentinel error surfaced to callers of ParseIPv4.","triggerScenarios":"ParseIPv4(dst, nil) or ParseIPv4(dst, []byte(\"\")) — e.g. passing an empty RemoteAddr/host header field, or a header that was never set.","commonSituations":"Extracting the client IP from a header (X-Forwarded-For, X-Real-IP) that the proxy did not set; reading a config value that is empty; splitting an address where the IP part is missing.","solutions":["Check len(ipStr) == 0 before calling ParseIPv4 and return a clear 'IP not provided' error or a default value.","Ensure the upstream header/proxy actually populates the field; add the proxy config that sets X-Forwarded-For.","Fall back to ctx.RemoteAddr() (or net.TCPAddrFromAddr) when the header-based IP is empty.","If an empty value is acceptable, wrap the call and treat this error as a no-op with a nil IP."],"exampleFix":"// before\nip, err := fasthttp.ParseIPv4(dst, hdr)\n// after\nif len(hdr) == 0 {\n    return nil, errors.New(\"client IP header missing\")\n}\nip, err := fasthttp.ParseIPv4(dst, hdr)","handlingStrategy":"validation","validationCode":"func parseIPOrDefault(dst net.IP, b []byte) (net.IP, error) {\n    if len(b) == 0 {\n        return nil, errors.New(\"IP address not provided\")\n    }\n    return fasthttp.ParseIPv4(dst, b)\n}","typeGuard":"func nonEmptyBytes(b []byte) bool { return len(b) > 0 }","tryCatchPattern":"ip, err := fasthttp.ParseIPv4(dst, hdr)\nif err != nil {\n    if len(hdr) == 0 {\n        ip = defaultIP // header absent\n    } else {\n        return err\n    }\n}","preventionTips":["Check header presence before parsing its value","Configure proxies to always set X-Forwarded-For","Fall back to ctx.RemoteAddr() when header-based IP is empty","Trim whitespace before the length check"],"tags":["ip-parsing","input-validation","empty-input"],"backgroundTag":"empty-input-value","analyzedSha":"c96f600972c6f4a7a30d664257b340ebe9d60124","analyzedAt":"2026-08-31T22:48:28.265Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}