{"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":"error","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/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/resolver/dns/dns_resolver.go#L251-L287","documentation":"Returned by lookupSRV when, after fetching SRV records and resolving each SRV target's A records, formatIP(a) fails for one of the returned addresses. formatIP uses netip.ParseAddr, so this fires when an A-record value is not a parseable IP literal (e.g. a CNAME string leaked through, or a malformed record).","triggerScenarios":"An SRV record points at a target whose LookupHost returns a non-IP string; a misbehaving DNS server returning names instead of addresses in the A lookup; EnableSRVLookups is true and grpclb SRV records reference bad targets.","commonSituations":"Self-hosted DNS that returns inconsistent A records; legacy grpclb configuration pointing at hostnames inside the SRV chain; DNS poisoning or split-horizon DNS returning text.","solutions":["If you do not use grpclb, leave EnableSRVLookups = false (the default) so SRV resolution is skipped.","Fix the upstream DNS so SRV targets resolve to valid IP A records.","Validate SRV records with dig/nslookup to find the malformed target."],"exampleFix":"// before\ngrpc.EnableSRVLookups = true // triggers SRV+A resolution\n// after (if grpclb is not used)\ngrpc.EnableSRVLookups = false","handlingStrategy":"validation","validationCode":"// Keep SRV lookups off unless grpclb is in use.\nif !usingGrpcLB {\n    grpc.EnableSRVLookups = false\n}","typeGuard":null,"tryCatchPattern":"// Surfaced as a resolver error; the dns resolver backs off and retries.\n// To eliminate it entirely, disable SRV lookups or fix upstream DNS.","preventionTips":["Leave EnableSRVLookups at its false default unless you run grpclb.","Keep SRV records pointing at resolvable IP A records.","Audit DNS with dig for SRV+A chains in grpclb setups."],"tags":["grpc","resolver","dns","srv-records","grpclb","ip-parsing"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}