{"record":{"id":"d8e3838ed5ea1ca5","repo":"owasp-amass/amass","slug":"failed-the-maximum-number-of-dns-attempts","errorCode":null,"errorMessage":"failed the maximum number of DNS attempts","messagePattern":"failed the maximum number of DNS attempts","errorType":"error_code","errorClass":"ErrFailedMaxDNSAttempts","httpStatus":null,"severity":"warning","filePath":"engine/plugins/support/resolvers.go","lineNumber":28,"sourceCode":"\t\"runtime\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/miekg/dns\"\n\t\"github.com/owasp-amass/resolve/conn\"\n\t\"github.com/owasp-amass/resolve/pool\"\n\t\"github.com/owasp-amass/resolve/selectors\"\n\t\"github.com/owasp-amass/resolve/servers\"\n\t\"github.com/owasp-amass/resolve/types\"\n\t\"github.com/owasp-amass/resolve/utils\"\n\t\"github.com/owasp-amass/resolve/wildcards\"\n\t\"golang.org/x/net/publicsuffix\"\n)\n\nvar (\n\tErrNameDoesNotExist     = errors.New(\"name does not exist\")\n\tErrNoRecordOfThisType   = errors.New(\"no record of this type\")\n\tErrFailedMaxDNSAttempts = errors.New(\"failed the maximum number of DNS attempts\")\n)\n\ntype baseline struct {\n\taddress string\n\tqps     int\n}\n\n// baselineResolvers is a list of trusted public DNS resolvers.\nvar baselineResolvers = []baseline{\n\t{\"8.8.8.8\", 5}, // Google Primary\n\t//\t{\"8.8.4.4\", 5},         // Google Secondary\n\t{\"95.85.95.85\", 2},     // Gcore DNS Primary\n\t{\"2.56.220.2\", 2},      // Gcore DNS Secondary\n\t{\"76.76.2.0\", 2},       // ControlD Primary\n\t{\"76.76.10.0\", 2},      // ControlD Secondary\n\t{\"9.9.9.9\", 2},         // Quad9 Primary\n\t{\"149.112.112.112\", 2}, // Quad9 Secondary\n\t{\"208.67.222.222\", 2},  // Cisco OpenDNS Home Primary","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/owasp-amass/amass/blob/79299dce87b0085db0f2f4ef3e9c52cccb49f514/engine/plugins/support/resolvers.go#L10-L46","documentation":"ErrFailedMaxDNSAttempts is a sentinel error returned when the resolver exhausts its retry budget — the internal query function gives up after repeatedly failing to obtain a valid response from available resolvers (timeouts, SERVFAIL, transient network errors). Unlike ErrNameDoesNotExist, it is transient: another attempt later may succeed. Callers in engine/plugins/dns (cname.go, ip.go) log a warning instead of treating it as a hard failure.","triggerScenarios":"Calling support.PerformQuery/query when every DNS attempt to the resolver pool fails (network timeouts, resolver unavailability, repeated non-success RCodes) until the maximum retry count is reached.","commonSituations":"Running bulk enumeration on a flaky network or behind a firewall blocking port 53; resolver rate-limiting the client; DNSSEC validation failures causing repeated SERVFAIL; container/VM without working DNS configuration.","solutions":["Retry the lookup later — the error is transient by design.","Check local DNS configuration (/etc/resolv.conf) and network reachability to the configured resolvers.","Reduce query concurrency/rate to avoid resolver throttling and increase per-query timeouts.","Log and continue, as the plugin handlers do (session Log().Warn), rather than aborting the enumeration."],"exampleFix":"// before\nrr, err := support.PerformQuery(ctx, name, dns.TypeA)\nif err != nil {\n    return err\n}\n// after\nrr, err := support.PerformQuery(ctx, name, dns.TypeA)\nif err != nil {\n    if err == support.ErrFailedMaxDNSAttempts {\n        log.Warn(\"DNS lookup exhausted retries, will retry later\", \"name\", name)\n        return nil\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"// Check DNS connectivity before running bulk enumeration\nr := &net.Resolver{}\n_, err := r.LookupHost(context.Background(), \"example.com\")\nif err != nil { log.Fatal(\"DNS unavailable: \", err) }","typeGuard":"func isMaxDNSAttempts(err error) bool { return errors.Is(err, support.ErrFailedMaxDNSAttempts) }","tryCatchPattern":"rr, err := support.PerformQuery(ctx, name, dns.TypeA)\nif errors.Is(err, support.ErrFailedMaxDNSAttempts) {\n    time.Sleep(backoff)\n    rr, err = support.PerformQuery(ctx, name, dns.TypeA)\n}","preventionTips":["Add exponential backoff between retries.","Throttle query rate to avoid resolver throttling.","Ensure /etc/resolv.conf points to working resolvers in containers/CI.","Log and continue per-asset, as the dns plugins do, instead of aborting scans."],"tags":["dns","retry-exhausted","transient"],"backgroundTag":"request-timeout","analyzedSha":"79299dce87b0085db0f2f4ef3e9c52cccb49f514","analyzedAt":"2026-09-06T08:22:48.198Z","contentChangedAt":"2026-09-06T08:22:48.198Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}