{"record":{"id":"9dcbf3c85935e810","repo":"lionsoul2014/ip2region","slug":"parse-ip-s-w-9dcbf3","errorCode":null,"errorMessage":"parse ip %s: %w","messagePattern":"parse ip (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"binding/golang/xdb/searcher.go","lineNumber":118,"sourceCode":"// IPVersion return the ip version\nfunc (s *Searcher) IPVersion() *Version {\n\treturn s.version\n}\n\n// GetIOCount return the global io count for the last search\nfunc (s *Searcher) GetIOCount() int {\n\treturn s.ioCount\n}\n\n// Search the region for the specified string or bytes ip address\nfunc (s *Searcher) Search(ip any) (string, error) {\n\tvar err error\n\tvar ipBytes []byte\n\tswitch v := ip.(type) {\n\tcase string:\n\t\tipBytes, err = ParseIP(v)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"parse ip %s: %w\", v, err)\n\t\t}\n\tcase []byte:\n\t\tipBytes = v\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"invalid ip value type %s\", v)\n\t}\n\n\t// ip version check\n\tif len(ipBytes) != s.version.Bytes {\n\t\treturn \"\", fmt.Errorf(\"invalid ip address(%s expected)\", s.version.Name)\n\t}\n\n\t// reset the global ioCount\n\ts.ioCount = 0\n\n\t// locate the segment index block based on the vector index\n\tvar il0, il1 = int(ipBytes[0]), int(ipBytes[1])\n\tvar idx = il0*VectorIndexCols*VectorIndexSize + il1*VectorIndexSize","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/lionsoul2014/ip2region/blob/c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1/binding/golang/xdb/searcher.go#L100-L136","documentation":"Go xdb.Searcher.Search: the string ip failed ParseIP, so it is neither a valid IPv4 nor IPv6 literal; the input string and the underlying parse error are wrapped together.","triggerScenarios":"Calling searcher.Search(ctx, \"999.1.2.3\") or any malformed string like \"abc\", \"1.2.3\", or an IPv6 literal with bad syntax; also passing a v4-only string to a v6 searcher if ParseIP rejects it.","commonSituations":"Log-line IP fields containing placeholders like \"-\" or \"unknown\"; user-supplied input not validated before lookup; trailing whitespace or port appended (\"1.2.3.4:8080\").","solutions":["Validate the IP string with net.ParseIP (or xdb.IsIPv4/IsIPv6) before calling Search.","Trim whitespace and strip any port suffix from the input string.","Check that the string family (v4 vs v6) matches the xdb file version the searcher was loaded for.","Handle the wrapped error by inspecting err.Unwrap() to distinguish parse failure from read failure."],"exampleFix":"// before\nregion, err := searcher.Search(ctx, rawIP)\n// after\nif net.ParseIP(strings.TrimSpace(rawIP)) == nil {\n    return \"\", fmt.Errorf(\"not an IP: %q\", rawIP)\n}\nregion, err := searcher.Search(ctx, strings.TrimSpace(rawIP))","handlingStrategy":"validation","validationCode":"ip := net.ParseIP(strings.TrimSpace(raw))\nif ip == nil {\n    return fmt.Errorf(\"invalid ip string: %q\", raw)\n}","typeGuard":"func isIPString(s string) bool { return net.ParseIP(strings.TrimSpace(s)) != nil }","tryCatchPattern":"region, err := searcher.Search(ctx, raw)\nif err != nil {\n    var parseErr error\n    if errors.Unwrap(err) != nil { parseErr = errors.Unwrap(err) }\n    return fmt.Errorf(\"lookup failed: %w (input=%q)\", parseErr, raw)\n}","preventionTips":["Trim and normalize IP strings from logs/user input before lookup.","Skip placeholders like \"-\" or \"unknown\" without calling Search.","Use net.ParseIP as a cheap pre-check.","Keep the raw value in your wrapped error for debugging."],"tags":["golang","ip-parsing","invalid-input"],"backgroundTag":"invalid-ip-address","analyzedSha":"c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1","analyzedAt":"2026-09-02T16:58:39.988Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}