{"record":{"id":"dd24c420c344f595","repo":"txthinking/brook","slug":"this-is-ipv6","errorCode":null,"errorMessage":"This is ipv6","messagePattern":"This is ipv6","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resolve.go","lineNumber":36,"sourceCode":"\tm.SetQuestion(host+\".\", dns.TypeAAAA)\n\tr, err := dns.Exchange(m, \"[2001:4860:4860::8888]:53\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tfor _, v := range r.Answer {\n\t\tif t, ok := v.(*dns.AAAA); ok {\n\t\t\treturn t.AAAA.String(), nil\n\t\t}\n\t}\n\treturn \"\", errors.New(\"Can not find IP\")\n}\n\nfunc Resolve4(host string) (string, error) {\n\tif net.ParseIP(host).To4() != nil {\n\t\treturn host, nil\n\t}\n\tif net.ParseIP(host).To16() != nil {\n\t\treturn \"\", errors.New(\"This is ipv6\")\n\t}\n\tm := &dns.Msg{}\n\tm.SetQuestion(host+\".\", dns.TypeA)\n\tr, err := dns.Exchange(m, \"8.8.8.8:53\")\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tfor _, v := range r.Answer {\n\t\tif t, ok := v.(*dns.A); ok {\n\t\t\treturn t.A.String(), nil\n\t\t}\n\t}\n\treturn \"\", errors.New(\"Can not find IP\")\n}\n","sourceCodeStart":18,"sourceCodeEnd":51,"githubUrl":"https://github.com/txthinking/brook/blob/5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8/resolve.go#L18-L51","documentation":"Resolve4 refuses to resolve hosts that are already literal IPv6 addresses. After net.ParseIP(host), if the address has a 16-byte (To16) representation but no 4-byte one, the library returns this error instead of attempting a DNS query, since an A lookup is meaningless for an IPv6 literal.","triggerScenarios":"Calling Resolve4(\"2001:db8::1\") or any IPv6 literal string. ParseIP succeeds, To4() is nil, To16() is non-nil, so the guard fires before any DNS traffic.","commonSituations":"Config or user input supplying an IPv6 address to an IPv4-only resolver; dual-stack code paths that pick Resolve4 without checking address family; reading addresses from URLs/host headers that may be v6.","solutions":["Check the address family first: if net.ParseIP(host) != nil && net.ParseIP(host).To4() == nil, call Resolve6(host) instead.","If IPv4 is mandatory, reject or normalize the input up front and surface a clear 'IPv4 required' validation error to the user.","Use a family-agnostic wrapper that parses the IP once and dispatches to Resolve4/Resolve6."],"exampleFix":"// before\nip, err := Resolve4(host) // fails with \"This is ipv6\"\n// after\nif ip := net.ParseIP(host); ip != nil && ip.To4() == nil {\n    return Resolve6(host)\n}\nreturn Resolve4(host)","handlingStrategy":"validation","validationCode":"ip := net.ParseIP(host)\nif ip != nil && ip.To4() == nil {\n    // it's IPv6 — route to Resolve6 instead\n}","typeGuard":"func isIPv4Literal(s string) bool {\n    ip := net.ParseIP(s)\n    return ip != nil && ip.To4() != nil\n}","tryCatchPattern":"ip, err := Resolve4(host)\nif err != nil && strings.Contains(err.Error(), \"ipv6\") {\n    return Resolve6(host)\n}","preventionTips":["Parse IPs once up front and dispatch by address family.","Validate user-supplied host/address inputs before choosing a resolver.","Make dual-stack wrappers the default entry point instead of Resolve4/Resolve6 directly."],"tags":["ipv6","address-family","invalid-argument","dns"],"backgroundTag":"invalid-argument-value","analyzedSha":"5cd13ef3b1fb574e88ebf2c1b5d95f2ebe1342c8","analyzedAt":"2026-09-06T04:35:00.432Z","contentChangedAt":"2026-09-06T04:35:00.432Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}