{"record":{"id":"289e261ba3ea33f8","repo":"grpc/grpc-go","slug":"dns-error-parsing-a-record-ip-address-v-v","errorCode":null,"errorMessage":"dns: error parsing A record IP address %v: %v","messagePattern":"dns: error parsing A record IP address (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/resolver/dns/dns_resolver.go","lineNumber":269,"sourceCode":"\tif err != nil {\n\t\terr = handleDNSError(err, \"SRV\") // may become nil\n\t\treturn nil, err\n\t}\n\tfor _, s := range srvs {\n\t\tlbAddrs, err := d.resolver.LookupHost(ctx, s.Target)\n\t\tif err != nil {\n\t\t\terr = handleDNSError(err, \"A\") // may become nil\n\t\t\tif err == nil {\n\t\t\t\t// If there are other SRV records, look them up and ignore this\n\t\t\t\t// one that does not exist.\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, err\n\t\t}\n\t\tfor _, a := range lbAddrs {\n\t\t\tip, err := formatIP(a)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"dns: error parsing A record IP address %v: %v\", a, err)\n\t\t\t}\n\t\t\taddr := ip + \":\" + strconv.Itoa(int(s.Port))\n\t\t\tnewAddrs = append(newAddrs, resolver.Address{Addr: addr, ServerName: s.Target})\n\t\t}\n\t}\n\treturn newAddrs, nil\n}\n\nfunc handleDNSError(err error, lookupType string) error {\n\tdnsErr, ok := err.(*net.DNSError)\n\tif ok && !dnsErr.IsTimeout && !dnsErr.IsTemporary {\n\t\t// Timeouts and temporary errors should be communicated to gRPC to\n\t\t// attempt another DNS query (with backoff).  Other errors should be\n\t\t// suppressed (they may represent the absence of a TXT record).\n\t\treturn nil\n\t}\n\tif err != nil {\n\t\terr = fmt.Errorf(\"dns: %v record lookup error: %v\", lookupType, err)","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/grpc/grpc-go/blob/0c51461d27177d997e14c642fe18c11668fc09a3/internal/resolver/dns/dns_resolver.go#L251-L287","documentation":"During SRV-record based gRPC load balancer discovery, lookupSRV at dns_resolver.go:255-273 resolves each SRV target's hostname via LookupHost, then parses each returned address as an IP with formatIP. If netip.ParseAddr fails (the resolver returned something that is not an IP), the resolver returns this error, aborting the SRV lookup for that record.","triggerScenarios":"Triggered when EnableSRVLookups is true, an SRV record is found for the host, and one of the addresses returned by LookupHost(s.Target) is not parseable by netip.ParseAddr. This indicates the underlying system resolver returned a non-IP string (e.g. a CNAME, a malformed record).","commonSituations":"A misbehaving DNS server returns a hostname or garbage where an A/AAAA record is expected, the SRV target resolves to a CNAME chain that leaks through as a name, or a custom net.Resolver returns non-standard results.","solutions":["Run a direct DNS query (dig SRV _grpclb._tcp.<host> and dig A <srv-target>) to see what the resolver returns.","If the DNS server is returning invalid data, fix the records on the authoritative server.","If SRV lookups are not needed, leave EnableSRVLookups at its default (false) to skip the SRV path entirely.","If using a custom net.Resolver via WithContextDialerOption/resolver option, ensure it returns only IP literals."],"exampleFix":"// before: SRV lookups enabled but DNS returns bad A records\n//   grpc.EnableSRVLookups = true\n\n// after: disable SRV (default) if not using grpclb\n//   // leave EnableSRVLookups = false (default)","handlingStrategy":"validation","validationCode":"package main\n\nimport (\n\t\"fmt\"\n\t\"net/netip\"\n)\n\n// If you supply a custom resolver result for SRV targets, ensure every address\n// is a valid IP literal.\nfunc allIPLiterals(addrs []string) error {\n\tfor _, a := range addrs {\n\t\tif _, err := netip.ParseAddr(a); err != nil {\n\t\t\treturn fmt.Errorf(\"non-IP in A result %q: %w\", a, err)\n\t\t}\n\t}\n\treturn nil\n}\n\n// func main() { _ = allIPLiterals }","typeGuard":null,"tryCatchPattern":"// The DNS resolver logs this at warning and returns it from the lookup; gRPC\n// will back off. Surface it through your resolver-error handler.\n//\n//   // Use grpclog.Component or grpc.WithReturnConnectionError to observe.\n//   // Treat SRV/A parse failures as transient unless persistent.","preventionTips":["Leave EnableSRVLookups disabled unless you actually use grpclb.","Run periodic DNS health checks (dig) against your SRV targets.","If using a custom net.Resolver, return only IP literals."],"tags":["dns","resolver","srv","grpclb","network","grpc"],"backgroundTag":null,"analyzedSha":"0c51461d27177d997e14c642fe18c11668fc09a3","analyzedAt":"2026-08-11T14:49:15.055Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}